- Reworked the connection object and the IO system

- Reworked the support for TRICS
- Added a second generation motor
This commit is contained in:
koennecke
2009-02-03 08:05:39 +00:00
parent f6d595665e
commit 361ee9ebea
119 changed files with 16455 additions and 3674 deletions

392
nread.c
View File

@@ -10,7 +10,7 @@
Telnet Functionality added: Mark Koennecke, January 1998
Revamped login to non telnet connection.
Mark Koennecke, October 20000
Mark Koennecke, October 2000
-----------------------------------------------------------------------------*/
#include <stdlib.h>
@@ -67,6 +67,7 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
int iReadTimeout;
int iEnd;
long lMagic;
pDynString conList;
} NetReader;
/*---------------------------------------------------------------------------
The structure used for an item in the Net Reader list of connections
@@ -97,7 +98,8 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
memset(pNew,0,sizeof(NetReader));
pNew->iList = LLDcreate(sizeof(NetItem));
if(pNew->iList < 0)
pNew->conList = CreateDynString(1024,1024);
if(pNew->iList < 0 || pNew->conList == NULL)
{
free(pNew);
return NULL;
@@ -121,6 +123,10 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
}
LLDdelete(self->iList);
if(self->conList != NULL)
{
DeleteDynString(self->conList);
}
free(self);
}
/*--------------------------------------------------------------------------*/
@@ -208,10 +214,12 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
if(pNew)
{
/* create connection object */
/* TODO
pRes = SCreateConnection(self->pMain->pSics,pNew,3);
*/
if(!pRes)
{
SICSLogWrite("Failure to allocate new Connection",eInternal);
SICSLogWrite("Failure to allocate new Connection",eInternal);
NETClosePort(pNew);
free(pNew);
return 0;
@@ -370,7 +378,9 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
if(pNew)
{
/* create connection object */
/* TODO
pRes = SCreateConnection(self->pMain->pSics,pNew,usSpy);
*/
if(!pRes)
{
SICSLogWrite("Failure to allocate new Connection",eInternal);
@@ -706,9 +716,6 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
int conCount = 0;
char num[50];
IPair *options = NULL;
char buffer[1024];
int bufferLen;
static int bufferFull=0;
self = (pNetRead)pData;
assert(self);
@@ -723,12 +730,13 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
return 0;
}
ANETprocess();
/* build the select mask */
FD_ZERO(&lMask);
iRet = LLDnodePtr2First(self->iList);
iCount = 0;
buffer[0] = '\0';
bufferLen = 0;
DynStringClear(self->conList);
while(iRet != 0)
{
LLDnodeDataTo(self->iList,&NItem);
@@ -736,14 +744,10 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
{
break;
}
snprintf(num,sizeof num, "%d, type %d:", NItem.pSock->sockid, NItem.eType);
if (bufferLen + strlen(num) < sizeof buffer) {
strcpy(buffer + bufferLen, num);
bufferLen += strlen(num);
} else {
if (bufferFull == 0) {
bufferFull = 1;
}
sprintf(num,"%d, type %d:", NItem.pSock->sockid, NItem.eType);
if(conCount < 100){
DynStringConcat(self->conList,num);
}
FD_SET(NItem.pSock->sockid,&lMask);
if(NItem.pSock->sockid > iCount)
@@ -751,17 +755,20 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
iCount = NItem.pSock->sockid;
}
conCount++;
if(conCount > 100){
WriteToCommandLog("WAYTOMANYCONNECTIONS> ", GetCharArray(self->conList));
}
iRet = LLDnodePtr2Next(self->iList);
}
if(conCount > 100){
WriteToCommandLog("WAYTOMANYCONNECTIONS> ", GetCharArray(self->conList));
}
snprintf(num,sizeof num,"%d", conCount);
IFSetOption(pSICSOptions,"ConnectionCount",num);
IFSetOption(pSICSOptions,"ConMask",buffer);
IFSetOption(pSICSOptions,"ConMask",GetCharArray(self->conList));
if (bufferFull == 1) {
bufferFull = 2;
WriteToCommandLog("BUFFERFULL>",buffer);
}
/* the select itself */
tmo.tv_usec = self->iReadTimeout;
@@ -1072,5 +1079,348 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
}
return 0;
}
/*===================================================================================
* new code to support the ANET network stuff
* =================================================================================*/
typedef struct {
pDynString command;
int state;
SConnection *pCon;
}CommandCBData, *pCommandCBData;
/*----------------------------------------------------------------------------------*/
static void killCommandCBData(void *data){
pCommandCBData self = (pCommandCBData)data;
if(self == NULL){
return;
}
if(self->command != NULL){
DeleteDynString(self->command);
}
free(self);
}
/*----------------------------------------------------------------------------------*/
static int testAndInvokeInterrupt(pCommandCBData self, int handle){
char *pPtr;
char buffer[512];
int iInt;
pPtr = GetCharArray(self->command);
if(strstr(pPtr,"INT1712") != NULL){
sscanf(pPtr, "%s %d",buffer, &iInt);
if(SCMatchRights(self->pCon,usUser)) {
TaskSignal(pServ->pTasker, SICSINT, &iInt);
snprintf(buffer,512, "INTERRUPT %d issued on sock %d",
iInt,handle);
WriteToCommandLog("SYS>", buffer);
if(iInt == eEndServer){
TaskStop(pServ->pTasker);
}
} else {
SCWrite(self->pCon,
"ERROR: insufficient privilege to invoke Interrupt",
eError);
}
return 1;
}
return 0;
}
/*----------------------------------------------------------------------------------*/
static int CommandDataCB(int handle, void *userData){
pCommandCBData self = (pCommandCBData)userData;
int i, length, status;
char *pPtr = NULL;
assert(self != NULL);
pPtr = ANETreadPtr(handle,&length);
if(pPtr == NULL){
return 1;
}
for(i = 0; i < length; i++){
switch(self->state){
case COLLECT:
if(pPtr[i] == '\r' || pPtr[i] == '\n'){
self->state = SKIPTERM;
if(!testAndInvokeInterrupt(self,handle)){
status = CostaTop(self->pCon->pStack, GetCharArray(self->command));
if(!status){
SCWrite(self->pCon,"ERROR: Busy", eError);
}
}
DynStringClear(self->command);
} else {
if(pPtr[i] != '\0'){
DynStringConcatChar(self->command, pPtr[i]);
}
}
break;
case SKIPTERM:
if(pPtr[i] != '\r' && pPtr[i] != '\n' && pPtr[i] != '\0'){
DynStringConcatChar(self->command, pPtr[i]);
self->state = COLLECT;
}
break;
}
}
ANETreadConsume(handle, length);
return 1;
}
/*----------------------------------------------------------------------------------*/
static int CommandAcceptCB(int handle, void *userData){
SConnection *pCon = NULL;
pCommandCBData usData = NULL;
pCon = SCreateConnection(pServ->pSics, handle, 3);
usData = malloc(sizeof(CommandCBData));
if(pCon == NULL || usData == NULL){
SICSLogWrite("Failure to allocate new Connection",eInternal);
return 0;
}
usData->command = CreateDynString(256,256);
if(usData->command == NULL){
SICSLogWrite("Failure to allocate new Connection",eInternal);
return 0;
}
usData->pCon = pCon;
usData->state = COLLECT;
TaskRegister(pServ->pTasker,
SCTaskFunction,
SCSignalFunction,
SCDeleteConnection,
pCon,
1);
ANETsetReadCallback(handle, CommandDataCB,
usData, killCommandCBData);
SCSendOK(pCon);
return 1;
}
/*-----------------------------------------------------------------------*/
static int ANETTelnetReply(int sockHandle, char code, char cChar)
{
char pReply[3];
pReply[0] = IAC;
pReply[1] = code;
pReply[2] = cChar;
ANETwrite(sockHandle,pReply,3);
return 1;
}
/*-----------------------------------------------------------------------*/
static int ANETTelnetProcess(int handle, void *usData){
pCommandCBData self = NULL;
int length, status, i;
int cChar;
char *pPtr = NULL;
char pError[256];
self = (pCommandCBData)usData;
assert(self != NULL);
pPtr = ANETreadPtr(handle,&length);
/* do telnet analysis of the data buffer */
for(i = 0; i < length; i++){
cChar = (int)pPtr[i];
#ifdef TELNETDEBUG
if( (cChar > 48) && (cChar < 128) ){
printf("char: %c\n",cChar);
} else {
printf("Control: %d\n",cChar);
}
#endif
/* Telnet status switching */
switch(self->state){
case tData:
switch(cChar){
case IAC:
self->state = tIAC;
break;
case '\r':
case '\n':
if(!testAndInvokeInterrupt(self,handle)){
status = CostaTop(self->pCon->pStack, GetCharArray(self->command));
if(!status){
SCWrite(self->pCon,"ERROR: Busy", eError);
}
}
self->state = tCR;
DynStringClear(self->command);
break;
case (char)8: /* backspace */
DynStringBackspace(self->command);
break;
case (char)0:/* ignore 0 character sent as end of text */
break;
default:
DynStringConcatChar(self->command,(char)cChar);
break;
} /* end of tData case */
break;
case tCR:
if(cChar == '\r' || cChar == '\n' || cChar == '\0'){
continue;
} else {
self->state = tData;
DynStringConcatChar(self->command,(char)cChar);
}
break;
case tIAC:
switch(cChar)
{
case IAC:
self->state = tData;
break;
case WILL:
self->state = tWill;
break;
case WONT:
self->state = tWont;
break;
case DONT:
self->state = tDont;
break;
case DO:
self->state = tDo;
break;
case EOR:
self->state = tData;
break;
case SB:
self->state = tSB;
break;
case EC:
DynStringBackspace(self->command);
self->state = tData;
break;
case EL:
DynStringClear(self->command);
self->state = tData;
break;
case IP:
SCSetInterrupt(self->pCon,eAbortBatch);
self->state = tData;
break;
default:
self->state = tData;
break;
} /* end of tIAC */
break;
case tWill: /* we do not do options! */
ANETTelnetReply(handle,DONT,cChar);
self->state = tData;
break;
case tWont: /* we do not do options! A Wont is sent by the client
if it cannot do a option we requested it to have. As
we do not try to force options, this should not happen
*/
self->state = tData;
break;
case tDo: /* we do not do options! */
ANETTelnetReply(handle,WONT,cChar);
self->state = tData;
break;
case tDont: /* we do not do options! A Dont is sent by the client
if it cannot do a option we requested it to have. As
we do not try to force options, this should not happen
*/
self->state = tData;
break;
case tSB: /* as we do not have options, we cannot have suboption
negotaitions. Something is seriously wrong when
we are here. It is a protocoll error. However, we
ignore it silently. tSB marks the start of the
subnegotiation. The current character must be the
option code we are dealing with.
*/
self->state = tSE;
break;
case tSE:
/* now we are in the suboption parameter. Normally data
should be copied to a suboption string buffer here
until SE.
*/
switch(cChar)
{
case IAC:
break;
case SE:
self->state = tData;
/* suboption interpretation would go here */
break;
default:
/* copy data to suboption buffer */
break;
}
break;
default:
/* There is something wrong here! */
sprintf(pError,"ERROR: bad telnet code %d", cChar);
SICSLogWrite(pError,eInternal);
self->state = tData;
break;
} /* end master swicth */
} /* end for loop */
ANETreadConsume(handle,length);
return 1;
}
/*----------------------------------------------------------------------------------*/
static int TelnetAcceptCB(int handle, void *userData){
SConnection *pCon = NULL;
pCommandCBData usData = NULL;
pTelTask pTel = NULL;
pCon = SCreateConnection(pServ->pSics, handle, 3);
usData = malloc(sizeof(CommandCBData));
if(pCon == NULL || usData == NULL){
SICSLogWrite("Failure to allocate new Connection",eInternal);
return 0;
}
usData->command = CreateDynString(256,256);
if(usData->command == NULL){
SICSLogWrite("Failure to allocate new Connection",eInternal);
return 0;
}
usData->pCon = pCon;
usData->state = tData;
/* Create a task object for the telnet connection */
pTel = CreateTelnet(pCon);
if(!pTel){
SICSLogWrite("Failure to allocate new Telnet Task Object",
eInternal);
SCDeleteConnection(pCon);
return 0;
}
/* register connection and task */
pCon->iTelnet = 1;
TaskRegister(pServ->pTasker,
TelnetTask,
TelnetSignal,
DeleteTelnet,
pTel,
1);
ANETsetReadCallback(handle, ANETTelnetProcess,
usData, killCommandCBData);
SCSendOK(pCon);
return 1;
}
/*------------------------------------------------------------------------------------*/
static void NREADlog(int level, char *txt, void *userData){
puts(txt);
}
/*------------------------------------------------------------------------------------*/
int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort){
ANETsetLog(NREADlog,NULL);
switch(eType){
case naccept:
return ANETopenServerPort(iPort,CommandAcceptCB,NULL);
break;
case taccept:
return ANETopenServerPort(iPort,TelnetAcceptCB,NULL);
break;
}
return 0;
}