Configurable terminators for normal protocols

r1973 | dcl | 2007-05-21 17:57:33 +1000 (Mon, 21 May 2007) | 2 lines
This commit is contained in:
Douglas Clowes
2007-05-21 17:57:33 +10:00
parent 4e5ea6a61c
commit 163b03b557
2 changed files with 177 additions and 16 deletions

View File

@@ -3,14 +3,35 @@
#include <asyncqueue.h> #include <asyncqueue.h>
int defaultSendCommand(pAsyncProtocol p, pAsyncTxn txn) { int defaultSendCommand(pAsyncProtocol p, pAsyncTxn txn) {
int i, iRet;
int state;
const char *term = "\r\n";
if (p->sendTerminator)
term = p->sendTerminator;
state = 0;
for (i = 0; i < txn->out_len; ++i) {
if (txn->out_buf[i] == 0x00) { /* end of transmission */
break;
}
else if (txn->out_buf[i] == term[state]) {
++state;
continue;
}
state = 0;
}
txn->txn_state = 0; txn->txn_state = 0;
/* TODO: anything? */ iRet = AsyncUnitWrite(txn->unit, txn->out_buf, txn->out_len);
return AsyncUnitWrite(txn->unit, txn->out_buf, txn->out_len); if (iRet <= 0)
return iRet;
if (term[state] != 0)
iRet = AsyncUnitWrite(txn->unit, term, strlen(term));
return iRet;
} }
int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch) { int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch) {
/* TODO: generic terminators */ const char *term = "\r\n";
char term[] = { 0x0D, 0x0A, 0x00 }; if (p->replyTerminator)
term = p->replyTerminator;
if (ch == term[txn->txn_state]) if (ch == term[txn->txn_state])
++txn->txn_state; ++txn->txn_state;
else else
@@ -27,14 +48,16 @@ int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch) {
} }
int defaultHandleEvent(pAsyncProtocol p, pAsyncTxn txn, int event) { int defaultHandleEvent(pAsyncProtocol p, pAsyncTxn txn, int event) {
/* TODO */ /* TODO: handle the event */
return AQU_POP_CMD;
} }
int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_len, int rsp_len) { int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_len, int rsp_len) {
/* TODO: generic terminators */
char term[] = { 0x0D, 0x0A, 0x00 };
int i; int i;
int state; int state;
const char *term = "\r\n";
if (p->sendTerminator)
term = p->sendTerminator;
state = 0; state = 0;
for (i = 0; i < cmd_len; ++i) { for (i = 0; i < cmd_len; ++i) {
if (cmd[i] == 0x00) { /* end of transmission */ if (cmd[i] == 0x00) { /* end of transmission */
@@ -48,10 +71,12 @@ int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_
state = 0; state = 0;
} }
if (term[state] == 0) { if (term[state] == 0) {
/* outgoing command is correctly terminated */
txn->out_buf = malloc(cmd_len + 1); txn->out_buf = malloc(cmd_len + 1);
memcpy(txn->out_buf, cmd, cmd_len + 1); memcpy(txn->out_buf, cmd, cmd_len + 1);
} }
else { else {
/* outgoing command is NOT correctly terminated */
int tlen = strlen(term); int tlen = strlen(term);
txn->out_buf = malloc(cmd_len + tlen + 1); txn->out_buf = malloc(cmd_len + tlen + 1);
memcpy(txn->out_buf, cmd, cmd_len); memcpy(txn->out_buf, cmd, cmd_len);
@@ -68,14 +93,98 @@ int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_
return 1; return 1;
} }
static const char* hex = "0123456789ABCDEF";
/*--------------------------------------------------------------------*/
static void encodeTerminator(char *result, char *terminator)
{
if (terminator)
while (*terminator) {
*result++ = '0';
*result++ = 'x';
*result++ = hex[(*terminator >> 4) &0xF];
*result++ = hex[(*terminator) &0xF];
++terminator;
}
*result = '\0';
return;
}
static int fromHex(const char* code) {
int icode = -1;
int result = -1;
if (code[0] == '0' && (code[1] == 'x' || code[1] == 'X')) {
if (code[2] >= '0' && code[2] <= '9')
icode = (code[2] - '0');
else if (code[2] >= 'a' && code[2] <= 'f')
icode = 10 + (code[2] - 'a');
else if (code[2] >= 'A' && code[2] <= 'F')
icode = 10 + (code[2] - 'A');
if (icode < 0)
return -1;
result = icode << 4;
icode = -1;
if (code[3] >= '0' && code[3] <= '9')
icode = (code[3] - '0');
else if (code[3] >= 'a' && code[3] <= 'f')
icode = 10 + (code[3] - 'a');
else if (code[3] >= 'A' && code[3] <= 'F')
icode = 10 + (code[3] - 'A');
if (icode < 0)
return -1;
result |= icode;
return result;
}
return -1;
}
/*--------------------------------------------------------------------*/
static char *decodeTerminator(char *code)
{
int count = 0, icode;
char *pResult;
char* pCh;
char* pQt = NULL; /* pointer to quote character if found */
if (code == NULL)
return NULL;
count = strlen(code);
pResult = (char *) malloc(count + 1);
if (!pResult)
return NULL;
memset(pResult, 0, count + 1);
pCh = pResult;
if (*code == '\'' || *code == '"') /* check for leading quote */
pQt = code++;
while (*code) {
if (pQt && *code == *pQt) /* check for trailing quote */
break;
if (code[0] == '\\' && code[1] == 'r') { /* CR */
*pCh++ = '\r';
code += 2;
}
else if (code[0] == '\\' && code[1] == 'n') { /* LF */
*pCh++ = '\n';
code += 2;
}
else if ((icode = fromHex(code)) >= 0) { /* Hex: 0xFF */
*pCh++ = icode;
code += 4;
}
else /* literal */
*pCh++ = *code++;
}
*pCh = '\0';
return pResult;
}
int AsyncProtocolNoAction(SConnection *pCon, SicsInterp *pSics, int AsyncProtocolNoAction(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]) void *pData, int argc, char *argv[])
{ {
char line[132]; char line[132];
pAsyncProtocol self = (pAsyncProtocol) pData; pAsyncProtocol self = (pAsyncProtocol) pData;
if (argc > 1) {
/* TODO: handle parameters like terminators */
}
snprintf(line, 132, "%s does not understand %s", argv[0], argv[1]); snprintf(line, 132, "%s does not understand %s", argv[0], argv[1]);
SCWrite(pCon, line, eError); SCWrite(pCon, line, eError);
return 0; return 0;
@@ -86,20 +195,68 @@ int AsyncProtocolAction(SConnection *pCon, SicsInterp *pSics,
{ {
char line[132]; char line[132];
pAsyncProtocol self = (pAsyncProtocol) pData; pAsyncProtocol self = (pAsyncProtocol) pData;
/* TODO: terminators */ if (argc > 1) {
snprintf(line, 132, "%s does not understand %s", argv[0], argv[1]); /* handle genecic parameters like terminators */
SCWrite(pCon, line, eError); if (strcasecmp(argv[1], "sendterminator") == 0) {
return 0; if (argc > 2) {
char* pPtr = decodeTerminator(argv[2]);
if (pPtr) {
if (self->sendTerminator)
free(self->sendTerminator);
self->sendTerminator = pPtr;
}
SCSendOK(pCon);
}
else
{
char term[132];
char line[1024];
encodeTerminator(term, self->sendTerminator);
sprintf(line, "%s.sendTerminator = \"%s\"", argv[0], term);
SCWrite(pCon, line, eValue);
}
return 1;
}
if (strcasecmp(argv[1], "replyterminator") == 0) {
if (argc > 2) {
char* pPtr = decodeTerminator(argv[2]);
if (pPtr) {
if (self->replyTerminator)
free(self->replyTerminator);
self->replyTerminator = pPtr;
}
SCSendOK(pCon);
}
else
{
char term[132];
char line[1024];
encodeTerminator(term, self->replyTerminator);
sprintf(line, "%s.replyTerminator = \"%s\"", argv[0], term);
SCWrite(pCon, line, eValue);
}
return 1;
}
}
/* TODO: other actions */
return AsyncProtocolNoAction(pCon, pSics, pData, argc,argv);
} }
void defaultKillPrivate(pAsyncProtocol p) { void defaultKillPrivate(pAsyncProtocol p) {
/* TODO: anything? */ if (p->privateData) {
/* TODO: anything? */
}
} }
void AsyncProtocolKill(void *pData) { void AsyncProtocolKill(void *pData) {
pAsyncProtocol self = (pAsyncProtocol) pData; pAsyncProtocol self = (pAsyncProtocol) pData;
DeleteDescriptor(self->pDes); if(self->pDes)
DeleteDescriptor(self->pDes);
/* TODO: more destruction maybe */ /* TODO: more destruction maybe */
if(self->sendTerminator != NULL)
free(self->sendTerminator);
if(self->replyTerminator != NULL)
free(self->replyTerminator);
if (self->killPrivate) if (self->killPrivate)
self->killPrivate(self); self->killPrivate(self);
} }
@@ -137,6 +294,8 @@ pAsyncProtocol AsyncProtocolCreate(SicsInterp *pSics, const char* protocolName,
self->handleEvent = defaultHandleEvent; self->handleEvent = defaultHandleEvent;
self->prepareTxn = defaultPrepareTxn; self->prepareTxn = defaultPrepareTxn;
self->killPrivate = defaultKillPrivate; self->killPrivate = defaultKillPrivate;
self->sendTerminator = strdup("\r\n");
self->replyTerminator = strdup("\r\n");
return self; return self;
} }

View File

@@ -48,6 +48,8 @@ struct __async_txn {
struct __async_protocol { struct __async_protocol {
pObjectDescriptor pDes; pObjectDescriptor pDes;
char* protocolName; char* protocolName;
char *sendTerminator;
char *replyTerminator;
void* privateData; void* privateData;
int (* sendCommand)(pAsyncProtocol p, pAsyncTxn txn); int (* sendCommand)(pAsyncProtocol p, pAsyncTxn txn);
int (* handleInput)(pAsyncProtocol p, pAsyncTxn txn, int ch); int (* handleInput)(pAsyncProtocol p, pAsyncTxn txn, int ch);