- design improvements in scriptcontext (sct send) and ascon (AsconBaseHandler)
- bug fixes
This commit is contained in:
207
ascon.c
207
ascon.c
@ -15,6 +15,7 @@
|
||||
#include "uselect.h"
|
||||
|
||||
static double lastClose = 0; /* time of last close operation */
|
||||
static AsconProtocol *protocols = NULL;
|
||||
|
||||
/*
|
||||
CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout
|
||||
@ -132,6 +133,10 @@ static void AsconConnect(Ascon * a)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (a->hostport == NULL) {
|
||||
AsconError(a, "no host:port given", 0);
|
||||
return;
|
||||
}
|
||||
colon = strchr(a->hostport, ':');
|
||||
if (colon == NULL)
|
||||
return;
|
||||
@ -167,28 +172,6 @@ static void AsconConnect(Ascon * a)
|
||||
return;
|
||||
}
|
||||
|
||||
int AsconStdInit(Ascon *a, SConnection *con, int argc, char *argv[])
|
||||
{
|
||||
a->fd = -1;
|
||||
a->state = AsconConnectStart;
|
||||
a->hostport = strdup(argv[1]);
|
||||
if (argc > 2) {
|
||||
a->sendTerminator = strdup(argv[2]);
|
||||
} else {
|
||||
a->sendTerminator = strdup("\n");
|
||||
}
|
||||
if (argc > 3) {
|
||||
a->timeout = atof(argv[3]);
|
||||
} else {
|
||||
a->timeout = 2.0; /* sec */
|
||||
}
|
||||
a->replyTerminator == NULL;
|
||||
if (argc > 4 && argv[4][0] != '\0') {
|
||||
a->replyTerminator = strdup(argv[4]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AsconReadGarbage(int fd)
|
||||
{
|
||||
fd_set rmask;
|
||||
@ -315,14 +298,14 @@ int AsconWriteChars(int fd, char *data, int length)
|
||||
|
||||
static double lastCall = 0;
|
||||
|
||||
int AsconStdHandler(Ascon * a)
|
||||
int AsconBaseHandler(Ascon * a)
|
||||
{
|
||||
int ret;
|
||||
int l;
|
||||
char chr;
|
||||
double now = DoubleTime();
|
||||
|
||||
if (now > lastCall + 0.5) { /* AsconStdHandler was not called since a long time (0.5 sec) */
|
||||
if (now > lastCall + 0.5) { /* AsconBaseHandler was not called since a long time (0.5 sec) */
|
||||
if (lastCall != 0) { /* extend timeout time (for debugging purposes) */
|
||||
a->start += now - lastCall - 0.5;
|
||||
}
|
||||
@ -343,26 +326,13 @@ int AsconStdHandler(Ascon * a)
|
||||
}
|
||||
break;
|
||||
case AsconWriteStart:
|
||||
if (strstr(GetCharArray(a->wrBuffer), "@@NOSEND@@") != NULL) {
|
||||
a->state = AsconWriteDone;
|
||||
} else {
|
||||
if (a->sendTerminator) {
|
||||
DynStringConcat(a->wrBuffer, a->sendTerminator);
|
||||
a->wrPos = 0;
|
||||
a->state = AsconWriting;
|
||||
}
|
||||
a->wrPos = 0;
|
||||
a->state = AsconWriting;
|
||||
break;
|
||||
case AsconWriting:
|
||||
if (a->readState) { /* last char was CR */
|
||||
ret = AsconReadChar(a->fd, &chr);
|
||||
if (ret > 0) {
|
||||
if (chr == '\n') {
|
||||
/* swallow LF after CR */
|
||||
a->readState = 0;
|
||||
} else {
|
||||
/* garbage character found */
|
||||
}
|
||||
}
|
||||
}
|
||||
AsconReadGarbage(a->fd);
|
||||
l = GetDynStringLength(a->wrBuffer) - a->wrPos;
|
||||
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l);
|
||||
@ -382,56 +352,24 @@ int AsconStdHandler(Ascon * a)
|
||||
break;
|
||||
case AsconReading:
|
||||
ret = AsconReadChar(a->fd, &chr);
|
||||
if (ret > 0) {
|
||||
a->start = DoubleTime();
|
||||
|
||||
if (a->replyTerminator != NULL) {
|
||||
if (strchr(a->replyTerminator, chr) != NULL) {
|
||||
DynStringConcatChar(a->rdBuffer, chr);
|
||||
DynStringConcatChar(a->rdBuffer, '\0');
|
||||
a->state = AsconReadDone;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (chr == '\n') {
|
||||
if (a->readState) { /* last char was CR */
|
||||
/* swallow LF after CR */
|
||||
a->readState = 0;
|
||||
chr = 0;
|
||||
} else {
|
||||
DynStringConcatChar(a->rdBuffer, '\0');
|
||||
a->state = AsconReadDone;
|
||||
break;
|
||||
}
|
||||
} else if (chr == '\r') {
|
||||
a->readState = 1; /* set 'last char was CR' */
|
||||
DynStringConcatChar(a->rdBuffer, '\0');
|
||||
a->state = AsconReadDone;
|
||||
break;
|
||||
if (ret <= 0) {
|
||||
if (ret < 0) {
|
||||
AsconError(a, "ASC5", errno);
|
||||
return 0;
|
||||
}
|
||||
if (a->timeout > 0) {
|
||||
if (DoubleTime() - a->start > a->timeout) {
|
||||
AsconError(a, "no response", 0);
|
||||
a->state = AsconTimeout;
|
||||
}
|
||||
}
|
||||
if (chr != 0) {
|
||||
if (DynStringConcatChar(a->rdBuffer, chr) == 0) {
|
||||
AsconError(a, "DynStringConcatChar failed:", ENOMEM);
|
||||
break;
|
||||
}
|
||||
a->readState = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (ret < 0) {
|
||||
AsconError(a, "ASC5", errno);
|
||||
return 1;
|
||||
}
|
||||
if (a->state == AsconReadDone) {
|
||||
DynStringConcatChar(a->rdBuffer, '\0');
|
||||
} else if (ret > 0) {
|
||||
return 0; /* characater read: recycle */
|
||||
}
|
||||
if (a->timeout > 0) {
|
||||
if (DoubleTime() - a->start > a->timeout) {
|
||||
AsconError(a, "no response", 0);
|
||||
a->state = AsconTimeout;
|
||||
}
|
||||
a->lastChar = chr;
|
||||
a->start = DoubleTime();
|
||||
if (DynStringConcatChar(a->rdBuffer, chr) == 0) {
|
||||
AsconError(a, "ASC6", errno);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -440,8 +378,6 @@ int AsconStdHandler(Ascon * a)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static AsconProtocol *protocols = NULL;
|
||||
|
||||
void AsconInsertProtocol(AsconProtocol *protocol) {
|
||||
protocol->next = protocols;
|
||||
protocols = protocol;
|
||||
@ -472,6 +408,88 @@ AsconHandler AsconSetHandler(Ascon *a, SConnection *con,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* --- standard handler ---- */
|
||||
|
||||
int AsconStdHandler(Ascon * a)
|
||||
{
|
||||
int result;
|
||||
char chr;
|
||||
int ret;
|
||||
|
||||
switch (a->state) {
|
||||
case AsconWriteStart:
|
||||
if (strstr(GetCharArray(a->wrBuffer), "@@NOSEND@@") != NULL) {
|
||||
a->state = AsconWriteDone;
|
||||
return 1;
|
||||
}
|
||||
break; /* go to the base handler */
|
||||
case AsconWriting:
|
||||
if (a->readState) { /* last char was CR */
|
||||
ret = AsconReadChar(a->fd, &chr);
|
||||
if (ret > 0) {
|
||||
if (chr == '\n') {
|
||||
/* swallow LF after CR */
|
||||
a->readState = 0;
|
||||
} else {
|
||||
/* garbage character found -> swallow */
|
||||
}
|
||||
}
|
||||
}
|
||||
break; /* go to the base handler */
|
||||
case AsconReading:
|
||||
result = AsconBaseHandler(a);
|
||||
if (result == 0)
|
||||
return 0;
|
||||
chr = a->lastChar;
|
||||
if (a->replyTerminator != NULL) {
|
||||
if (strchr(a->replyTerminator, chr) != NULL) {
|
||||
DynStringConcatChar(a->rdBuffer, '\0');
|
||||
a->state = AsconReadDone;
|
||||
}
|
||||
} else {
|
||||
if (chr == '\n') {
|
||||
if (a->readState) { /* last char was CR */
|
||||
/* swallow LF after CR */
|
||||
a->readState = 0;
|
||||
} else {
|
||||
DynStringBackspace(a->rdBuffer); /* remove LF */
|
||||
DynStringConcatChar(a->rdBuffer, '\0');
|
||||
a->state = AsconReadDone;
|
||||
}
|
||||
} else if (chr == '\r') {
|
||||
a->readState = 1; /* set 'last char was CR' */
|
||||
DynStringBackspace(a->rdBuffer); /* remove CR */
|
||||
DynStringConcatChar(a->rdBuffer, '\0');
|
||||
a->state = AsconReadDone;
|
||||
}
|
||||
}
|
||||
return 1; /* base handler was already called */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return AsconBaseHandler(a);
|
||||
}
|
||||
|
||||
int AsconStdInit(Ascon *a, SConnection *con, int argc, char *argv[])
|
||||
{
|
||||
a->hostport = strdup(argv[1]);
|
||||
if (argc > 2) {
|
||||
a->sendTerminator = strdup(argv[2]);
|
||||
} else {
|
||||
a->sendTerminator = strdup("\n");
|
||||
}
|
||||
if (argc > 3) {
|
||||
a->timeout = atof(argv[3]);
|
||||
} else {
|
||||
a->timeout = 2.0; /* sec */
|
||||
}
|
||||
a->replyTerminator = NULL;
|
||||
if (argc > 4 && argv[4][0] != '\0') {
|
||||
a->replyTerminator = strdup(argv[4]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* --- implementation of higher level interface ---- */
|
||||
|
||||
char *ConcatArgs(int argc, char *argv[])
|
||||
@ -489,6 +507,15 @@ Ascon *AsconMake(SConnection * con, int argc, char *argv[])
|
||||
SCWrite(con, "ERROR: no memory", eError);
|
||||
return NULL;
|
||||
}
|
||||
a->fd = -1;
|
||||
a->state = AsconConnectStart;
|
||||
a->timeout = 2.0; /* 2 sec default */
|
||||
a->reconnectInterval = 10; /* 10 sec default */
|
||||
a->replyTerminator = NULL;
|
||||
a->sendTerminator = NULL;
|
||||
a->hostport = NULL;
|
||||
a->responseValid = 0;
|
||||
|
||||
a->handler = AsconSetHandler(a, con, argc, argv);
|
||||
if (a->handler == NULL) {
|
||||
args = ConcatArgs(argc, argv);
|
||||
@ -501,7 +528,7 @@ Ascon *AsconMake(SConnection * con, int argc, char *argv[])
|
||||
a->rdBuffer = CreateDynString(60, 63);
|
||||
a->wrBuffer = CreateDynString(60, 63);
|
||||
a->errmsg = CreateDynString(60, 63);
|
||||
a->responseValid = 0;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user