SICS-128: The reactor status protocol now just searches for a line containing "Power:" and returns it as the reactor status.
This commit is contained in:
@ -2,7 +2,36 @@
|
|||||||
* @brief
|
* @brief
|
||||||
* Implements a simple protocol to GET reactor status using an HTTP/1.1 GET.
|
* Implements a simple protocol to GET reactor status using an HTTP/1.1 GET.
|
||||||
* It sets the UserAgent as SICS to avoid re-directs because we don't handle them.
|
* It sets the UserAgent as SICS to avoid re-directs because we don't handle them.
|
||||||
* If the HTTP status is not OK then it returns the status in the data buffer.
|
* If the HTTP status is not OK or if the driver fails to find a line that
|
||||||
|
* contains the "Power:" field then it returns the unprocessed reply
|
||||||
|
* characters in the data buffer.
|
||||||
|
*
|
||||||
|
* The reply is expected to have a form similar to the following,
|
||||||
|
* HTTP/1.1 200 OK
|
||||||
|
* Date: Thu, 26 Feb 2015 01:27:30 GMT
|
||||||
|
* Server: Oracle-Application-Server-10g/10.1.3.5.0 Oracle-HTTP-Server
|
||||||
|
* Content-Location: /reactor.jsp
|
||||||
|
* Content-Type: text/plain; charset=UTF-8
|
||||||
|
* Set-Cookie: JSESSIONID=74646fa7cf3cdf53a371694a33ab760cd649631d758f416d916c6d1b496a477b.e34Pc3qNbh4RaO0Ma3yMbxaRaN0Ke0; path=/Bragg
|
||||||
|
* Connection: close
|
||||||
|
* Transfer-Encoding: chunked
|
||||||
|
*
|
||||||
|
* 4f
|
||||||
|
* Power: 19.381588; CNS Out: 25.76; TG123: 1; CG123: 1; TG4: Open; HB1: 0; HB2: 1
|
||||||
|
*
|
||||||
|
* 0
|
||||||
|
*
|
||||||
|
* It should have no more than 512 characters excluding the HTTP OK status.
|
||||||
|
* Each line is expected to be terminated with a \r\n.
|
||||||
|
* The reply is expected to begin with "HTTP/1.1 200 OK"
|
||||||
|
* A line is identified as the status message if and only if it includes
|
||||||
|
* "Power:" regardless of case.
|
||||||
|
* The reply is expected to end with 0\r\n\r\n
|
||||||
|
*
|
||||||
|
* Processing lines is simplified by discarding \r characters and then just
|
||||||
|
* checking for \n.
|
||||||
|
* NOTE: This implies that \n should not be used in the status line as a
|
||||||
|
* delimiter.
|
||||||
*/
|
*/
|
||||||
#include "../made_config.h"
|
#include "../made_config.h"
|
||||||
#include <sics.h>
|
#include <sics.h>
|
||||||
@ -16,73 +45,78 @@
|
|||||||
#define USERAGENT "User-Agent: SICS\r\n"
|
#define USERAGENT "User-Agent: SICS\r\n"
|
||||||
#endif
|
#endif
|
||||||
#define HOST "Host: neutron.ansto.gov.au\r\n"
|
#define HOST "Host: neutron.ansto.gov.au\r\n"
|
||||||
|
/* Assume that the first field in the reactor status starts with "Power" */
|
||||||
|
#define PWR_FLD "Power"
|
||||||
|
#define PWR_FLD_LEN 5
|
||||||
|
|
||||||
enum replystates {START, HEADER, CHKHEADEREND, MSG};
|
enum replystates {START, CHK_PWR_FLD, MSG, END_MSG, DRAIN_REPLY};
|
||||||
static pAsyncProtocol OPAL_Protocol = NULL;
|
static pAsyncProtocol OPAL_Protocol = NULL;
|
||||||
|
|
||||||
/* The header and message are followed by the character sequences given below,
|
/* The message is assumed to start with "Power:" and terminated with crlf.
|
||||||
* HEADER cr lf cr lf <msg len> cr lf
|
|
||||||
* MESSAGE cr lf 0x30 cr lf cr lf
|
|
||||||
* So we assume that the header is terminated by two consecutive crlf char
|
|
||||||
* pairs which are eventually followed by another crlf
|
|
||||||
* The message is assumed to be terminated by a crlf pair eventually followed
|
|
||||||
* by two more crlf pairs of characters
|
* by two more crlf pairs of characters
|
||||||
* Processing is simplified by discarding cr chars and counting lf chars */
|
* Processing of line terminators is simplified by discarding cr chars */
|
||||||
static int OPAL_Rx(pAsyncProtocol p, pAsyncTxn txn, int ch) {
|
static int OPAL_Rx(pAsyncProtocol p, pAsyncTxn txn, int ch) {
|
||||||
|
char *fldptr;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
static int nlctr = 0;
|
static int char_ctr = 0, newline_ctr = 0;
|
||||||
static enum replystates state = START;
|
static enum replystates state = START;
|
||||||
|
|
||||||
|
if (char_ctr++ >= txn->inp_len) {
|
||||||
|
char_ctr = 0;
|
||||||
|
newline_ctr = 0;
|
||||||
|
state = START;
|
||||||
|
return AQU_POP_CMD;
|
||||||
|
}
|
||||||
if (ch == '\r') {
|
if (ch == '\r') {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case START:
|
case START:
|
||||||
if (ch == '\n') {
|
if (ch == '\n') {
|
||||||
/* check HTTP status */
|
/* check HTTP status is OK before proceeding */
|
||||||
if ( strncmp(txn->inp_buf, HTTP_OK, strlen(HTTP_OK) ) == 0 ) {
|
if ( strncmp(txn->inp_buf, HTTP_OK, strlen(HTTP_OK) ) == 0 ) {
|
||||||
txn->inp_idx = 0;
|
txn->inp_idx = 0;
|
||||||
nlctr = 0;
|
state = CHK_PWR_FLD;
|
||||||
state = HEADER;
|
|
||||||
} else
|
} else
|
||||||
ret = AQU_POP_CMD;
|
ret = AQU_POP_CMD;
|
||||||
} else if (txn->inp_idx < txn->inp_len)
|
} else
|
||||||
txn->inp_buf[txn->inp_idx++] = ch;
|
txn->inp_buf[txn->inp_idx++] = ch;
|
||||||
else
|
|
||||||
ret = AQU_POP_CMD;
|
|
||||||
break;
|
break;
|
||||||
case HEADER:
|
case CHK_PWR_FLD:
|
||||||
if (ch == '\n') {
|
if (ch == '\n') {
|
||||||
nlctr++;
|
|
||||||
state = CHKHEADEREND;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CHKHEADEREND:
|
|
||||||
if (nlctr == 1 && ch == '\n')
|
|
||||||
nlctr++;
|
|
||||||
else if (nlctr == 1 && ch != '\n') {
|
|
||||||
txn->inp_idx = 0;
|
txn->inp_idx = 0;
|
||||||
nlctr = 0;
|
} else if (ch == ':') {
|
||||||
state = HEADER;
|
if ( txn->inp_idx >= PWR_FLD_LEN ) {
|
||||||
} else if (nlctr == 2 && ch == '\n') {
|
/* Check for "Power" field anywhere in status line */
|
||||||
txn->inp_idx = 0;
|
fldptr = &txn->inp_buf[txn->inp_idx - PWR_FLD_LEN];
|
||||||
nlctr = 0;
|
if ( strncasecmp(fldptr, PWR_FLD, PWR_FLD_LEN) == 0 ) {
|
||||||
state = MSG;
|
state = MSG;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
txn->inp_buf[txn->inp_idx++] = ch;
|
||||||
break;
|
break;
|
||||||
case MSG:
|
case MSG:
|
||||||
if (txn->inp_idx >= txn->inp_len)
|
if (ch == '\n') {
|
||||||
ret = AQU_POP_CMD;
|
state = END_MSG;
|
||||||
if (nlctr == 0 && ch != '\n')
|
} else {
|
||||||
txn->inp_buf[txn->inp_idx++] = ch;
|
txn->inp_buf[txn->inp_idx++] = ch;
|
||||||
else if (nlctr == 2 && ch == '\n')
|
}
|
||||||
|
break;
|
||||||
|
case END_MSG:
|
||||||
|
if (ch == '0') {
|
||||||
|
state = DRAIN_REPLY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DRAIN_REPLY:
|
||||||
|
newline_ctr++;
|
||||||
|
if (newline_ctr >= 2)
|
||||||
ret = AQU_POP_CMD;
|
ret = AQU_POP_CMD;
|
||||||
else
|
|
||||||
nlctr++;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ret == AQU_POP_CMD) {
|
if (ret == AQU_POP_CMD) {
|
||||||
nlctr = 0;
|
char_ctr = 0;
|
||||||
|
newline_ctr = 0;
|
||||||
state = START;
|
state = START;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -116,7 +150,7 @@ static int OPAL_PrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int
|
|||||||
if (txn->inp_buf != NULL) {
|
if (txn->inp_buf != NULL) {
|
||||||
free(txn->inp_buf);
|
free(txn->inp_buf);
|
||||||
}
|
}
|
||||||
txn->inp_len = rsp_len;
|
txn->inp_len = 512;
|
||||||
txn->inp_idx = 0;
|
txn->inp_idx = 0;
|
||||||
txn->txn_state = 0;
|
txn->txn_state = 0;
|
||||||
txn->txn_status = 0;
|
txn->txn_status = 0;
|
||||||
|
Reference in New Issue
Block a user