
- Fixed performance problems in many protocol drivers. SKIPPED: psi/julprot.c psi/phytron.c psi/pmacprot.c psi/polterwrite.c psi/spss7.c
156 lines
3.9 KiB
C
156 lines
3.9 KiB
C
/*
|
|
* genbinprot.c
|
|
*
|
|
* This is a generic binary protocol handler for scriptcontext. It expects a
|
|
* command of the form:
|
|
*
|
|
* writepointer:writecount:readpointer:readcount
|
|
*
|
|
* And will writecount bytes from the data area writepointer and
|
|
* read readcount bytes into the memory area under readpointer.
|
|
* If writecount is 0, the nothing will be written. This can
|
|
* be used to read a binary message in parts. Both writepointer and
|
|
* readpointer are memory addresses in hexadecimal.
|
|
*
|
|
* This is a workaround for the essential weakness of devser not being
|
|
* able to work with binary protocols.
|
|
*
|
|
* Created on: Jul 7, 2010
|
|
* Author: koennecke
|
|
*/
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <sics.h>
|
|
#include <ascon.h>
|
|
#include <ascon.i>
|
|
#include <stptok.h>
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
typedef struct {
|
|
char *writePointer;
|
|
unsigned int toWrite;
|
|
char *readPointer;
|
|
unsigned int readCount;
|
|
unsigned int toRead;
|
|
}GenBin, *pGenBin;
|
|
/*------------------------------------------------------------------*/
|
|
static void initGenBin(Ascon *a)
|
|
{
|
|
pGenBin self = (pGenBin)a->private;
|
|
char *pPtr = NULL, pToken[60];
|
|
long lval;
|
|
|
|
pPtr = GetCharArray(a->wrBuffer);
|
|
|
|
pPtr = stptok(pPtr,pToken,60,":");
|
|
sscanf(pToken,"%lx",&lval);
|
|
self->writePointer = (char *)lval;
|
|
|
|
pPtr = stptok(pPtr,pToken,60,":");
|
|
sscanf(pToken,"%d",&self->toWrite);
|
|
|
|
pPtr = stptok(pPtr,pToken,60,":");
|
|
sscanf(pToken,"%lx",&lval);
|
|
self->readPointer = (char *)lval;
|
|
|
|
pPtr = stptok(pPtr,pToken,60,":");
|
|
sscanf(pToken,"%d",&self->toRead);
|
|
|
|
a->wrPos = 0;
|
|
self->readCount = 0;
|
|
}
|
|
/*------------------------------------------------------------------*/
|
|
static int GenBinHandler(Ascon *a)
|
|
{
|
|
pGenBin self = (pGenBin)a->private;
|
|
unsigned int toWrite;
|
|
int ret;
|
|
char chr;
|
|
|
|
switch(a->state){
|
|
case AsconWriteStart:
|
|
AsconReadGarbage(a->fd);
|
|
initGenBin(a);
|
|
a->state = AsconWriting;
|
|
break;
|
|
case AsconWriting:
|
|
toWrite = self->toWrite - a->wrPos;
|
|
if(toWrite == 0){
|
|
a->state = AsconWriteDone;
|
|
} else {
|
|
ret = AsconWriteChars(a->fd, self->writePointer+a->wrPos, toWrite);
|
|
if (ret < 0) {
|
|
if (errno != EINTR && errno != EAGAIN) {
|
|
AsconError(a, "send failed:", errno);
|
|
}
|
|
} else {
|
|
a->wrPos += ret;
|
|
if(a->wrPos >= self->toWrite){
|
|
a->state = AsconWriteDone;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case AsconReading:
|
|
if(self->readCount >= self->toRead){
|
|
a->state = AsconReadDone;
|
|
DynStringCopy(a->rdBuffer,"OK");
|
|
} else {
|
|
ret = AsconReadChar(a->fd, &chr);
|
|
if (ret < 0) {
|
|
/* EINTR means we must retry */
|
|
if (errno != EINTR && errno != EAGAIN) {
|
|
AsconError(a, "AsconReadChar failed:", errno);
|
|
}
|
|
return 1;
|
|
} else if (ret > 0) {
|
|
a->start = DoubleTime();
|
|
self->readPointer[self->readCount] = chr;
|
|
self->readCount++;
|
|
} else if (ret == 0) {
|
|
if (a->timeout > 0) {
|
|
if (DoubleTime() - a->start > a->timeout) {
|
|
AsconError(a, "read timeout", 0);
|
|
a->state = AsconTimeout;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
return AsconStdHandler(a);
|
|
}
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int GenBinInit(Ascon * a, SConnection * con, int argc, char *argv[])
|
|
{
|
|
pGenBin priv = NULL;
|
|
|
|
priv = calloc(sizeof(GenBin), 1);
|
|
a->fd = -1;
|
|
a->state = AsconConnectStart;
|
|
a->reconnectInterval = 10;
|
|
a->hostport = strdup(argv[1]);
|
|
if (argc > 2) {
|
|
a->timeout = atof(argv[2]);
|
|
} else {
|
|
a->timeout = 2.0; /* sec */
|
|
}
|
|
a->private = priv;
|
|
a->killPrivate = free;
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
void AddGenBinProtocoll()
|
|
{
|
|
AsconProtocol *prot = NULL;
|
|
|
|
prot = calloc(sizeof(AsconProtocol), 1);
|
|
prot->name = strdup("genbin");
|
|
prot->init = GenBinInit;
|
|
prot->handler = GenBinHandler;
|
|
AsconInsertProtocol(prot);
|
|
}
|