- design improvements in scriptcontext (sct send) and ascon (AsconBaseHandler)

- bug fixes
This commit is contained in:
zolliker
2009-03-03 14:07:43 +00:00
parent 0dc196becb
commit 2e060ccf73
8 changed files with 292 additions and 172 deletions

207
ascon.c
View File

@ -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;
}