- Added two new protocols: for the Juelich chopper and for SINQHM HTTP

This commit is contained in:
koennecke
2008-06-11 13:37:48 +00:00
parent 90497e4beb
commit c8b8d4f301
5 changed files with 314 additions and 2 deletions

80
julprot.c Normal file
View File

@ -0,0 +1,80 @@
/**
* This is a protocol implementation for the new SICS asynchronous I/O
* infrastructure and the Juelich chopper system as used at MARS.
*
* The Juelich chopper control program likes checksums to come with
* messages and uses $ as both send and reply terminators.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, June 2008
*/
#include <errno.h>
#include <ascon.h>
#include <ascon.i>
#include <dynstring.h>
static int calculateJulCheckSum(char *realCommand){
int i, checkSum = 0;
for(i = 1; i < strlen(realCommand); i++){
checkSum += (int)realCommand[i];
}
return checkSum;
}
/*---------------------------------------------------------------------------*/
int JulchoHandler(Ascon *a){
char *data = NULL;
int checkSum, ret;
char checkBuffer[30], chr;
switch(a->state){
case AsconWriteStart:
data = GetCharArray(a->wrBuffer);
checkSum = calculateJulCheckSum(data);
snprintf(checkBuffer,30,"{%d}$", checkSum);
DynStringConcat(a->wrBuffer,checkBuffer);
a->state = AsconWriting;
a->wrPos = 0;
break;
case AsconReading:
ret = AsconReadChar(a->fd, &chr);
if(ret < 0){
AsconError(a, "AsconReadChar failed:", errno);
return 1;
} else if (ret > 0) {
a->start = DoubleTime();
if(chr == '$'){
DynStringConcatChar(a->rdBuffer, '\0');
a->state = AsconReadDone;
break;
} else {
if (DynStringConcatChar(a->rdBuffer, chr) == 0) {
AsconError(a, "DynStringConcatChar failed:", ENOMEM);
break;
}
}
} else if(ret == 0){
if (a->timeout > 0) {
if (DoubleTime() - a->start > a->timeout) {
AsconError(a, "read timeout", 0);
a->state = AsconTimeout;
}
}
}
break;
default:
return AsconStdHandler(a);
}
return 1;
}
/*-------------------------------------------------------------------------*/
void AddJulChoProtocoll(){
AsconProtocol *prot = NULL;
prot = calloc(sizeof(AsconProtocol), 1);
prot->name = strdup("julcho");
prot->init = AsconStdInit;
prot->handler = JulchoHandler;
AsconInsertProtocol(prot);
}

View File

@ -22,7 +22,7 @@ OBJ=psi.o buffer.o ruli.o dmc.o nxsans.o nextrics.o sps.o pimotor.o \
$(MZOBJ) amordrive.o amorset.o tcpdornier.o sinqhttp.o\ $(MZOBJ) amordrive.o amorset.o tcpdornier.o sinqhttp.o\
dgrambroadcast.o sinq.o tabledrive.o tcpdocho.o julcho.o \ dgrambroadcast.o sinq.o tabledrive.o tcpdocho.o julcho.o \
ritastorage.o poldizug.o audinelib.o delcam.o el737hpdrivsps.o \ ritastorage.o poldizug.o audinelib.o delcam.o el737hpdrivsps.o \
rebin.o sanslirebin.o lmd200.o slsvme.o rebin.o sanslirebin.o lmd200.o slsvme.o julprot.o sinqhttpprot.o
.SECONDARY.: sanslirebin.c .SECONDARY.: sanslirebin.c

11
psi.c
View File

@ -75,6 +75,11 @@ extern int MakeSansliRebin(SConnection *pCon, SicsInterp *pSics, void *pData,
/* from lmd200.c */ /* from lmd200.c */
extern int MakeLMD200(SConnection *pCon, SicsInterp *pSics, void *pData, extern int MakeLMD200(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]); int argc, char *argv[]);
/* from julchoprot.c */
extern void AddJulChoProtocoll();
/* from sinqhttpprot.c */
extern void AddHttpProtocoll();
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
void SiteInit(void) { void SiteInit(void) {
@ -94,6 +99,12 @@ void SiteInit(void) {
INIT(HaakeStartup); INIT(HaakeStartup);
INIT(AmiStartup); INIT(AmiStartup);
/*
* SICS specific Asynchronous I/O protocols
*/
AddJulChoProtocoll();
AddHttpProtocoll();
} }

221
sinqhttpprot.c Normal file
View File

@ -0,0 +1,221 @@
/**
* This is an asynchronous protocol implementation for HTTP.
* It includes special features to store binary data coming
* from a SINQ http histogram memory in a sinqdata object.
* Which has to be specified on initialisation.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, June 2008
*/
#include <ascon.h>
#include <ascon.i>
#include <ghttp.h>
#include <sicsdata.h>
#include <HistMem.h>
/*---------------------------------------------------------------------*/
typedef struct {
ghttp_request *request;
char *userName;
char *password;
pSICSData binData;
}HttpProt, *pHttpProt;
/*---------------------------------------------------------------------*/
static int configRequest(Ascon *a){
pHttpProt pHttp = (pHttpProt)a->private;
pDynString request;
char *uri = NULL;
request = CreateDynString(64,64);
if(request == NULL){
AsconError(a,"Out of memory", 122);
return 0;
}
DynStringConcat(request,"http://");
DynStringConcat(request,a->hostport);
DynStringConcatChar(request,'/');
DynStringConcat(request,GetCharArray(a->wrBuffer));
uri = GetCharArray(request);
ghttp_clean(pHttp->request);
ghttp_set_type(pHttp->request,ghttp_type_get);
ghttp_set_header(pHttp->request,"connection", "keep-alive");
if(ghttp_set_uri(pHttp->request,uri) < 0){
AsconError(a,"Bad URL", a->state);
return 0;
}
if(pHttp->userName != NULL && pHttp->password != NULL){
ghttp_set_authinfo(pHttp->request,
pHttp->userName, pHttp->password);
}
ghttp_set_sync(pHttp->request,ghttp_async);
ghttp_prepare(pHttp->request);
DeleteDynString(request);
return 1;
}
/*---------------------------------------------------------------------*/
static int HttpHandler(Ascon *a) {
ghttp_status status;
pHttpProt pHttp = (pHttpProt)a->private;
char *pPtr = NULL, *pType = NULL;
HistInt *hmData = NULL;
int i, len;
switch (a->state) {
case AsconKillMe: return 0;
case AsconConnectStart:
a->state = AsconConnecting;
break;
case AsconConnecting:
a->state = AsconConnectDone; /* success */
break;
case AsconWriteStart:
if(configRequest(a)){
a->state = AsconWriting;
}
break;
case AsconWriting:
status = ghttp_process(pHttp->request);
if(status == ghttp_error){
ghttp_close(pHttp->request);
configRequest(a);
status = ghttp_process(pHttp->request);
}
if(status == ghttp_error){
AsconError(a,"Server error", 123);
DynStringConcat(a->rdBuffer,"Server error");
a->state = AsconReadDone;
} else {
a->state = AsconWriteDone;
}
a->start = DoubleTime();
DynStringClear(a->rdBuffer);
break;
case AsconReadStart:
status = ghttp_process(pHttp->request);
switch(status){
case ghttp_not_done:
if(DoubleTime() > a->start + a->timeout){
AsconError(a," read timeout", 0);
a->state = AsconTimeout;
/* this to clear the line */
ghttp_close(pHttp->request);
}
return 1;
case ghttp_done:
a->state = AsconReading;
break;
case ghttp_error:
/*
* A first error may not be an error but a
* reconnect
*/
ghttp_close(pHttp->request);
configRequest(a);
status = ghttp_process(pHttp->request);
if(status == ghttp_error){
AsconError(a,"Server error", a->state);
DynStringConcat(a->rdBuffer,"Server error");
a->state = AsconReadDone;
}
break;
default:
printf("Hugo\n");
break;
}
break;
case AsconReading:
pPtr = ghttp_get_body(pHttp->request);
len = ghttp_get_body_len(pHttp->request);
if(strstr(pPtr,"ERROR") != NULL){
AsconError(a,pPtr, a->state);
DynStringConcat(a->rdBuffer,pPtr);
} else if(strstr(pPtr,"Authentication Error") != NULL){
DynStringConcat(a->rdBuffer,pPtr);
AsconError(a,pPtr, a->state);
} else {
pType = (char *)ghttp_get_header(pHttp->request,"Content-Type");
if(strstr(pType,"sinqhm") == NULL){
/* text data */
for(i = 0; i < len; i++){
DynStringConcatChar(a->rdBuffer, pPtr[i]);
}
} else {
hmData = (HistInt *)pPtr;
clearSICSData(pHttp->binData);
for(i = 0; i < len/sizeof(HistInt); i++){
setSICSDataInt(pHttp->binData, i, htonl(hmData[i]));
}
DynStringCopy(a->rdBuffer,"SICSDATA");
}
}
a->state = AsconReadDone;
break;
default:
return AsconStdHandler(a);
}
return 1;
}
/*------------------------------------------------------------------------*/
static void killHttp(void *data){
pHttpProt prot = (pHttpProt)data;
if(prot == NULL){
return;
}
if(prot->request != NULL){
ghttp_close(prot->request);
}
if(prot->password != NULL){
free(prot->password);
}
if(prot->userName != NULL){
free(prot->userName);
}
free(prot);
}
/*------------------------------------------------------------------------*/
static int HttpProtInit(Ascon *a, SConnection *con,
int argc, char *argv[]){
pHttpProt pHttp = NULL;
pHttp = calloc(sizeof(HttpProt), 1);
if(pHttp == NULL){
SCWrite(con,"ERROR: out of memory in HttpProtInit", eError);
return 0;
}
if(argc < 3){
return 0;
}
a->hostport = strdup(argv[1]);
pHttp->binData = (pSICSData)FindCommandData(pServ->pSics,
argv[2], "SICSData");
if(pHttp->binData == NULL){
SCWrite(con,"ERROR: SICSData objct not found", eError);
return 0;
}
if(argc > 3){
a->timeout = atof(argv[3]);
} else {
a->timeout = 10.;
}
if(argc > 5){
pHttp->userName = strdup(argv[4]);
pHttp->password = strdup(argv[5]);
}
pHttp->request = ghttp_request_new();
a->private = pHttp;
a->killPrivate = killHttp;
a->state = AsconConnectStart;
return 1;
}
/*-------------------------------------------------------------------------*/
void AddHttpProtocoll(){
AsconProtocol *prot = NULL;
prot = calloc(sizeof(AsconProtocol), 1);
prot->name = strdup("sinqhttp");
prot->init = HttpProtInit;
prot->handler = HttpHandler;
AsconInsertProtocol(prot);
}