Files
sics/genbinprot.c
koennecke 3ee1865f9b - Introduced a new trace facility
- Fixed performance problems in many protocol drivers.


SKIPPED:
	psi/julprot.c
	psi/phytron.c
	psi/pmacprot.c
	psi/polterwrite.c
	psi/spss7.c
2011-06-29 07:53:54 +00:00

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