Add host / port constructor methods

r1704 | dcl | 2007-03-23 13:56:40 +1100 (Fri, 23 Mar 2007) | 2 lines
This commit is contained in:
Douglas Clowes
2007-03-23 13:56:40 +11:00
parent 54e5ebb47e
commit 1a5c864950
2 changed files with 177 additions and 51 deletions

View File

@@ -11,7 +11,9 @@
*/ */
#include <sys/time.h> #include <sys/time.h>
#include <arpa/inet.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <netdb.h>
#include <sics.h> #include <sics.h>
#include <rs232controller.h> #include <rs232controller.h>
#include "network.h" #include "network.h"
@@ -41,25 +43,65 @@ struct __MultiChan {
struct __MultiChanController { struct __MultiChanController {
pObjectDescriptor pDes; pObjectDescriptor pDes;
char* mcc_name; char* mcc_name;
char* pHost; char* pHost;
int iPort; int iPort;
int iDelay; /* intercommand delay in milliseconds */ int iDelay; /* intercommand delay in milliseconds */
int timeout; int timeout;
int retries; int retries;
struct timeval tvLastCmd; /* time of completion of last command */ struct timeval tvLastCmd; /* time of completion of last command */
int unit_count; /* number of units connected */ int unit_count; /* number of units connected */
pMultiChan units; /* head of unit chain */ pMultiChan units; /* head of unit chain */
prs232 controller; /* associated RS232 controller object */ prs232 rs232c; /* associated RS232 controller object */
pMC_Cmd command_head; /* first/next command in queue */ pMC_Cmd command_head; /* first/next command in queue */
pMC_Cmd command_tail; /* last command in queue */ pMC_Cmd command_tail; /* last command in queue */
pNWContext nw_ctx; /* NetWait context handle */ pNWContext nw_ctx; /* NetWait context handle */
pNWTimer nw_tmr; /* NetWait timer handle */ pNWTimer nw_tmr; /* NetWait timer handle */
mkChannel* pSock; /* socket address */
}; };
static pMultiChanController mcc_array[FD_SETSIZE]; static pMultiChanController mcc_array[FD_SETSIZE];
static int mcc_index = 0; static int mcc_index = 0;
/* ---------------------------- Local ------------------------------------
CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout
*/
static int
CreateSocketAdress(
struct sockaddr_in *sockaddrPtr, /* Socket address */
char *host, /* Host. NULL implies INADDR_ANY */
int port) /* Port number */
{
struct hostent *hostent; /* Host database entry */
struct in_addr addr; /* For 64/32 bit madness */
(void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));
sockaddrPtr->sin_family = AF_INET;
sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
if (host == NULL) {
addr.s_addr = INADDR_ANY;
} else {
hostent = gethostbyname(host);
if (hostent != NULL) {
memcpy((char *) &addr,
(char *) hostent->h_addr_list[0], (size_t) hostent->h_length);
} else {
addr.s_addr = inet_addr(host);
if (addr.s_addr == (unsigned long)-1) {
return 0; /* error */
}
}
}
/*
* There is a rumor that this assignment may require care on
* some 64 bit machines.
*/
sockaddrPtr->sin_addr.s_addr = addr.s_addr;
return 1;
}
static void MC_Notify(pMultiChanController self, int event) static void MC_Notify(pMultiChanController self, int event)
{ {
pMultiChan unit; pMultiChan unit;
@@ -75,7 +117,7 @@ static int MC_Reconnect(pMultiChanController self)
int flag = 1; int flag = 1;
char line[132]; char line[132];
iRet = NETReconnect(self->controller->pSock); iRet = NETReconnect(self->pSock);
if (iRet <= 0) { if (iRet <= 0) {
snprintf(line, 132, "Disconnect on MultiChan '%s'", self->mcc_name); snprintf(line, 132, "Disconnect on MultiChan '%s'", self->mcc_name);
SICSLogWrite(line, eStatus); SICSLogWrite(line, eStatus);
@@ -94,7 +136,7 @@ static int CommandTimeout(void* cntx, int mode);
static int StartCommand(pMultiChanController self) static int StartCommand(pMultiChanController self)
{ {
pMC_Cmd myCmd = self->command_head; pMC_Cmd myCmd = self->command_head;
mkChannel* sock = self->controller->pSock; mkChannel* sock = self->pSock;
if (myCmd == NULL) if (myCmd == NULL)
return OKOK; return OKOK;
@@ -221,7 +263,7 @@ static int MyCallback(void* context, int mode)
int iRet; int iRet;
char reply[1]; char reply[1];
iRet = NETRead(self->controller->pSock, reply, 1, 0); iRet = NETRead(self->pSock, reply, 1, 0);
if (iRet < 0) { /* TODO: EOF */ if (iRet < 0) { /* TODO: EOF */
iRet = MC_Reconnect(self); iRet = MC_Reconnect(self);
if (iRet <= 0) if (iRet <= 0)
@@ -262,7 +304,7 @@ mkChannel* MultiChanGetSocket(pMultiChan unit)
{ {
assert(unit); assert(unit);
assert(unit->mcc); assert(unit->mcc);
return unit->mcc->controller->pSock; return unit->mcc->pSock;
} }
int MultiChanEnque(pMultiChan unit, void* context, MCC_Transmit tx, MCC_Receive rx) int MultiChanEnque(pMultiChan unit, void* context, MCC_Transmit tx, MCC_Receive rx)
@@ -447,41 +489,91 @@ int MultiChanAction(SConnection *pCon, SicsInterp *pSics,
return 0; return 0;
} }
static pMultiChanController MC_Create(const char* host) static pMultiChanController MC_Create(const char* host, const char* port)
{ {
int i; int i;
pMultiChanController self = NULL; pMultiChanController self = NULL;
prs232 ctlr = NULL; prs232 ctlr = NULL;
mkChannel* channel = NULL;
/* try to find the MCC with this name */ if (host == NULL)
self = (pMultiChanController)FindCommandData(pServ->pSics, host, "MultiChan"); return NULL;
if (self == NULL) {
ctlr = (prs232)FindCommandData(pServ->pSics, host, "RS232 Controller"); /* try the MCC with this name */
if(ctlr == NULL || ctlr->pSock == NULL) { self = (pMultiChanController) FindCommandData(pServ->pSics, host, "MultiChan");
/* try the RS232 Controller with this name */
if (self == NULL && port == NULL) {
ctlr = (prs232) FindCommandData(pServ->pSics, host, "RS232 Controller");
if(ctlr == NULL) {
char line[132];
snprintf(line, 132, "ERROR: RS232 Controller '%s' is not found in MultiChan", host);
SICSLogWrite(line, eError);
return NULL; return NULL;
} }
channel = ctlr->pSock;
if (channel == NULL) {
char line[132];
snprintf(line, 132, "ERROR: RS232 Controller '%s' is not connected in MultiChan", host);
SICSLogWrite(line, eError);
return NULL;
}
/* look for mcc with same controller */
for (i = 0; i < mcc_index; ++i) for (i = 0; i < mcc_index; ++i)
if (mcc_array[i]->controller == ctlr) { if (mcc_array[i]->rs232c == ctlr) {
self = mcc_array[i]; self = mcc_array[i];
break; break;
} }
if (self == NULL) {
self = (pMultiChanController) malloc(sizeof(MultiChanController));
if (self == NULL)
return NULL;
memset(self, 0, sizeof(MultiChanController));
self->controller = ctlr;
self->pDes = CreateDescriptor("MultiChan");
mcc_array[mcc_index++] = self;
}
} else {
for (i = 0; i < mcc_index; ++i)
if (mcc_array[i] == self) {
break;
}
if (i == mcc_index)
mcc_array[mcc_index++] = self;
} }
/* try host and port */
if (self == NULL && ctlr == NULL) {
int port_no = atoi(port);
if (port_no == 0) {
struct servent *sp=NULL;
sp = getservbyname(port, NULL);
if (sp)
port_no = ntohs(sp->s_port);
}
if (port_no > 0) {
struct sockaddr_in sa;
if (CreateSocketAdress(&sa, host, port_no)) {
/* look for mcc with same address */
for (i = 0; i < mcc_index; ++i)
if (mcc_array[i]->pSock->adresse.sin_port == sa.sin_port
&& mcc_array[i]->pSock->adresse.sin_addr.s_addr == sa.sin_addr.s_addr) {
self = mcc_array[i];
break;
}
}
if (self == NULL) {
channel = NETConnectWithFlags(host, port_no, 0);
/* TODO */
}
}
}
if (self == NULL) {
if (ctlr == NULL && channel == NULL)
return NULL;
self = (pMultiChanController) malloc(sizeof(MultiChanController));
if (self == NULL)
return NULL;
memset(self, 0, sizeof(MultiChanController));
self->rs232c = ctlr;
self->pSock = channel;
self->pDes = CreateDescriptor("MultiChan");
mcc_array[mcc_index++] = self;
}
for (i = 0; i < mcc_index; ++i)
if (mcc_array[i] == self) {
break;
}
if (i == mcc_index)
mcc_array[mcc_index++] = self;
return self; return self;
} }
@@ -490,7 +582,7 @@ static int MC_Init(pMultiChanController self)
/* TODO: Init the controller */ /* TODO: Init the controller */
if (self->nw_ctx == NULL) if (self->nw_ctx == NULL)
NetWatchRegisterCallback(&self->nw_ctx, NetWatchRegisterCallback(&self->nw_ctx,
self->controller->pSock->sockid, self->pSock->sockid,
MyCallback, MyCallback,
self); self);
return 1; return 1;
@@ -511,11 +603,18 @@ static void MC_Kill(void* pData)
NetWatchRemoveTimer(self->nw_tmr); NetWatchRemoveTimer(self->nw_tmr);
if (self->mcc_name) if (self->mcc_name)
free(self->mcc_name); free(self->mcc_name);
if (self->rs232c == NULL) {
NETClosePort(self->pSock);
free(self->pSock);
}
free(self); free(self);
return; return;
} }
} }
/*
* \brief make a multichannel controller from the command line
*/
int MultiChanFactory(SConnection *pCon, SicsInterp *pSics, int MultiChanFactory(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]) void *pData, int argc, char *argv[])
{ {
@@ -530,10 +629,22 @@ int MultiChanFactory(SConnection *pCon, SicsInterp *pSics,
return 0; return 0;
} }
/* try to find an existing mcc with this name */
pNew = (pMultiChanController) FindCommandData(pServ->pSics, argv[1], "MultiChan");
if (pNew != NULL) {
char line[132];
snprintf(line, 132, "ERROR: MultiChan '%s' already exists", argv[1]);
SCWrite(pCon, line, eError);
return 1;
}
/* /*
create data structure and open port create data structure and open port
*/ */
pNew = MC_Create(argv[2]); if (argc > 3)
pNew = MC_Create(argv[2], argv[3]);
else
pNew = MC_Create(argv[2], NULL) ;
if(!pNew) if(!pNew)
{ {
@@ -566,7 +677,14 @@ int MultiChanFactory(SConnection *pCon, SicsInterp *pSics,
return 1; return 1;
} }
int MultiChanCreate(const char* name, pMultiChan* handle) /*
* \brief make a multichannel controller from a named rs232 controller
*
* \param name the name of the SICS "RS232 Controller" object
* \param handle the handle to the multichannel controller object
* \return 0 for FAILURE, 1 for SUCCESS
*/
int MultiChanCreateHost(const char* host, const char* port, pMultiChan* handle)
{ {
int status; int status;
pMultiChanController self = NULL; pMultiChanController self = NULL;
@@ -574,7 +692,7 @@ int MultiChanCreate(const char* name, pMultiChan* handle)
*handle = NULL; *handle = NULL;
self = MC_Create(name); self = MC_Create(host, port);
if (self == NULL) if (self == NULL)
return 0; return 0;
status = MC_Init(self); status = MC_Init(self);
@@ -590,14 +708,18 @@ int MultiChanCreate(const char* name, pMultiChan* handle)
return 1; return 1;
} }
int MultiChanDestroy(pMultiChan chan) int MultiChanCreate(const char* host, pMultiChan* handle) {
return MultiChanCreateHost(host, NULL, handle);
}
int MultiChanDestroy(pMultiChan unit)
{ {
assert(chan); assert(unit);
assert(chan->mcc); assert(unit->mcc);
pMultiChanController self = chan->mcc; pMultiChanController self = unit->mcc;
pMultiChan* pNxt = &self->units; pMultiChan* pNxt = &self->units;
while (*pNxt) { while (*pNxt) {
if (*pNxt == chan) { if (*pNxt == unit) {
*pNxt = (*pNxt)->next; *pNxt = (*pNxt)->next;
break; break;
} }
@@ -607,7 +729,7 @@ int MultiChanDestroy(pMultiChan chan)
if (self->unit_count <= 0) { if (self->unit_count <= 0) {
MC_Kill(self); MC_Kill(self);
} }
free(chan); free(unit);
return 1; return 1;
} }

View File

@@ -24,6 +24,10 @@ int MultiChanFactory(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]); void *pData, int argc, char *argv[]);
int MultiChanCreate(const char* controller, pMultiChan* handle); int MultiChanCreate(const char* controller, pMultiChan* handle);
int MultiChanCreateHost(const char* host,
const char* port,
pMultiChan* handle);
int MultiChanDestroy(pMultiChan handle); int MultiChanDestroy(pMultiChan handle);
int MultiChanReconnect(pMultiChan handle); int MultiChanReconnect(pMultiChan handle);