Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

nsd.c

Go to the documentation of this file.
00001 /*
00002 
00003 NeuroServer
00004  
00005 A collection of programs to translate between EEG data and TCP network
00006 messages. This is a part of the OpenEEG project, see http://openeeg.sf.net
00007 for details.
00008     
00009 Copyright (C) 2003, 2004 Rudi Cilibrasi (cilibrar@ofb.net)
00010      
00011 This library is free software; you can redistribute it and/or
00012 modify it under the terms of the GNU Lesser General Public
00013 License as published by the Free Software Foundation; either
00014 version 2.1 of the License, or (at your option) any later version.
00015          
00016 This library is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 Lesser General Public License for more details.
00020             
00021 You should have received a copy of the GNU Lesser General Public
00022 License along with this library; if not, write to the Free Software
00023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00024                 
00025 */
00026                 
00027 
00028 #include <stdio.h>
00029 #include <ctype.h>
00030 #include <fcntl.h>
00031 #include <assert.h>
00032 #include <string.h>
00033 #include <openedf.h>
00034 #include <nsnet.h>
00035 #include <nsutil.h>
00036 #include <config.h>
00037 #include <neuro/cmdhandler.h>
00038 #include "nsd.h"
00039 
00040 #define MAXEDFCHANNELS 64
00041 
00042 #define TIMEOUT 30
00043 
00044 enum RoleCode { Unknown,  EEG, Display, Controller };
00045 
00046 struct EDFDecodedConfig current;
00047 
00048 static char *lineBuf;
00049 
00050 struct Client {
00051         sock_t fd;
00052         enum RoleCode role;
00053         int markedForDeletion;
00054         int headerLen;
00055         time_t lastAlive;
00056         int isDisplaying[MAXCLIENTS];;
00057         int linePos;
00058         struct InputBuffer ib;
00059         struct OutputBuffer ob;
00060         char lineBuf[MAXLEN];
00061         char headerBuf[MAXHEADERLEN];
00062 };
00063 
00064 struct Client clients[MAXCLIENTS];
00065 int clientCount = 0;
00066 
00067 const char *stringifyRole(enum RoleCode role);
00068 int countInRole(enum RoleCode role);
00069 void sendClientMsg(int cliInd, const char *msg);
00070 void sendClientMsgNL(int cliInd, const char *msg);
00071 
00072 void sendClientMsgNL(int cliInd, const char *msg)
00073 {
00074         sendClientMsg(cliInd, msg);
00075         sendClientMsg(cliInd, "\r\n");
00076 }
00077 
00078 const char *getLineBuf(void)
00079 {
00080         return lineBuf;
00081 }
00082 
00083 void sendClientMsg(int cliInd, const char *msg)
00084 {
00085         int retval = writen(clients[cliInd].fd, msg,strlen(msg), &clients[cliInd].ob);
00086 //      printf("Tried to send to %d:%s", cliInd, msg);
00087 //      rprintf("Tried to write %d bytes, got %d retval\n", strlen(msg), retval);
00088         if (retval < 0) {
00089                 rprintf("Got write error... %d\n", retval);
00090                 clients[cliInd].markedForDeletion = 1;
00091 #if 0
00092 #ifdef __MINGW32__
00093                 int winerr;
00094                 winerr = WSAGetLastError();
00095                 if (winerr == WSAENOTCONN)
00096                         clients[cliInd].markedForDeletion = 1;
00097 #endif
00098 #endif
00099         }
00100         if (retval > 0)
00101                 rtime(&clients[cliInd].lastAlive);
00102         
00103 }
00104 
00105 void sendResponseOK(int cliInd)
00106 {
00107         sendClientMsg(cliInd, "200 OK\r\n");
00108         /*rtime(&clients[cliInd].lastAlive); */
00109 }
00110 
00111 void sendResponseBadRequest(int cliInd)
00112 {
00113         sendClientMsg(cliInd, "400 BAD REQUEST\r\n");
00114 }
00115 
00116 
00122 void cmdgo(struct CommandHandler *ch, int cliInd)
00123 {
00124         if (clients[cliInd].role == Controller) {
00125                 int who;
00126                 fetchIntParameters(ch, &who, 1);
00127                 if (who >= 0 && who < clientCount && clients[who].role == EEG) {
00128                         rprintf("Sending go command from %d to %d \n", cliInd,who);
00129                         sendResponseOK(cliInd);
00130                         sendClientMsgNL(who,"go");
00131                         return;
00132                 }
00133         }
00134         sendResponseBadRequest(cliInd);
00135 }
00136 
00137 void cmdnogo(struct CommandHandler *ch, int cliInd)
00138 {
00139         if (clients[cliInd].role == Controller) {
00140                 int who;
00141                 fetchIntParameters(ch, &who, 1);
00142                 if (who >= 0 && who < clientCount && clients[who].role == EEG) {
00143                         rprintf("Sending nogo command from %d to %d \n", cliInd,who);
00144                         sendResponseOK(cliInd);
00145                         sendClientMsgNL(who,"nogo");
00146                         return;
00147                 }
00148         }
00149         sendResponseBadRequest(cliInd);
00150 }
00151 
00152 
00153 
00154 
00155 void cmdRole(struct CommandHandler *ch, int cliInd)
00156 {
00157         rprintf("Handling role with cliInd %d\n", cliInd);
00158         sendResponseOK(cliInd);
00159         sendClientMsgNL(cliInd, stringifyRole(clients[cliInd].role));
00160 }
00161 
00162 void cmdUnwatch(struct CommandHandler *ch, int cliInd)
00163 {
00164         if (clients[cliInd].role == Display) {
00165                 int who;
00166                 fetchIntParameters(ch, &who, 1);
00167                 if (who >= 0 && who < clientCount && clients[who].role == EEG) {
00168                         sendResponseOK(cliInd);
00169                         clients[who].isDisplaying[cliInd] = 0;
00170                         return;
00171                 }
00172         }
00173         sendResponseBadRequest(cliInd);
00174 }
00175 
00176 
00177 void cmdWatch(struct CommandHandler *ch, int cliInd)
00178 {
00179         if (clients[cliInd].role == Display) {
00180                 int who;
00181                 fetchIntParameters(ch, &who, 1);
00182                 if (who >= 0 && who < clientCount && clients[who].role == EEG) {
00183                         sendResponseOK(cliInd);
00184                         clients[who].isDisplaying[cliInd] = 1;
00185                         return;
00186                 }
00187         }
00188         sendResponseBadRequest(cliInd);
00189 }
00190 
00191 void cmdDataFrame(struct CommandHandler *ch, int cliInd)
00192 {
00193         int vals[MAXEDFCHANNELS];
00194         int samples[MAXEDFCHANNELS+2];
00195         /* vals[0] == pktCounter */
00196         /* vals[1] == channelCount */
00197         fetchIntParameters(ch, vals, 2);
00198         if (vals[1] > 0 && vals[1] < MAXEDFCHANNELS) {
00199                 int i;
00200                 char buf[MAXLEN];
00201                 int bufPos = 0;
00202                 // rprintf("Fetching %d parameters\n", vals[1] + 2);
00203                 fetchIntParameters(ch, samples, vals[1] + 2);
00204                 sendResponseOK(cliInd);
00205                 bufPos += sprintf(buf+bufPos, "! 0");
00206                 for (i = 0; i < vals[1] + 2; i += 1) {
00207                         bufPos += sprintf(buf+bufPos, " %d", samples[i]);
00208                 }
00209                 bufPos += sprintf(buf+bufPos, "\r\n");
00210                 if (vals[0] == 0) {
00211 //                      rprintf("Sending packet <%s>\n", buf); 
00212                         fflush(stdout);
00213                 }
00214                 for (i = 0; i < clientCount; ++i) {
00215                         if (clients[cliInd].isDisplaying[i]) {
00216                                 sendClientMsg(i, buf);
00217                         }
00218                 }
00219         }
00220         else
00221                 sendResponseBadRequest(cliInd);
00222 }
00223 
00224 void cmdGetHeader(struct CommandHandler *ch, int cliInd)
00225 {
00226         if (clients[cliInd].role == Display) {
00227                 int who;
00228                 fetchIntParameters(ch, &who, 1);
00229                 if (who >= 0 && who < clientCount && clients[who].role == EEG && clients[who].headerLen) {
00230                         sendResponseOK(cliInd);
00231                         sendClientMsgNL(cliInd, clients[who].headerBuf);
00232                         return;
00233                 }
00234         }
00235         sendResponseBadRequest(cliInd);
00236 }
00237 
00238 void cmdSetHeader(struct CommandHandler *ch, int cliInd)
00239 {
00240         const char *buf;
00241         const char *hdr;
00242         struct EDFDecodedConfig tmp;
00243         if (clients[cliInd].role != EEG) {
00244                 sendResponseBadRequest(cliInd);
00245                 return;
00246         }
00247         buf = getLineBuf();
00248         hdr = buf + 10; // strlen("setheader ");
00249         rprintf("Got header:\n");
00250         rprintf("The header is <%s>\n", hdr);
00251         readEDFString(&tmp, hdr, strlen(buf));
00252         makeREDFConfig(&current, &tmp);
00253         clients[cliInd].headerLen = sizeof(clients[0].headerBuf);
00254         writeEDFString(&current, clients[cliInd].headerBuf, &clients[cliInd].headerLen);
00255         if (memcmp(clients[cliInd].headerBuf, hdr, clients[cliInd].headerLen) != 0) {
00256                 printf("Warning: changed header from <%s> to <%s>\n", hdr, clients[cliInd].headerBuf);
00257         }
00258         sendResponseOK(cliInd);
00259 }
00260 
00261 void cmdStatus(struct CommandHandler *ch, int cliInd)
00262 {
00263         char buf[16384];
00264         int bufPos = 0, i;
00265         bufPos += sprintf(buf+bufPos, "%d clients connected\r\n", clientCount);
00266         for (i = 0; i < clientCount; ++i)
00267                 bufPos += sprintf(buf+bufPos, "%d:%s\r\n", i, stringifyRole(clients[i].role));
00268         sendResponseOK(cliInd);
00269         sendClientMsg(cliInd, buf);
00270 }
00271 
00272 void cmdClose(struct CommandHandler *ch, int cliInd)
00273 {
00274         sendResponseOK(cliInd);
00275         clients[cliInd].markedForDeletion = 1;
00276 }
00277 
00278 void cmdDisplay(struct CommandHandler *ch, int cliInd)
00279 {
00280         if (clients[cliInd].role == Unknown) {
00281                 clients[cliInd].role = Display;
00282                 sendResponseOK(cliInd);
00283                 return;
00284         }
00285         sendResponseBadRequest(cliInd);
00286 }
00287 
00288 void cmdEEG(struct CommandHandler *ch, int cliInd)
00289 {
00290         if (clients[cliInd].role == Unknown) {
00291                 clients[cliInd].role = EEG;
00292                 sendResponseOK(cliInd);
00293                 return;
00294         }
00295         sendResponseBadRequest(cliInd);
00296 }
00297 
00298 void cmdControl(struct CommandHandler *ch, int cliInd)
00299 {
00300         if (clients[cliInd].role == Unknown && countInRole(Controller) == 0) {
00301                 clients[cliInd].role = Controller;
00302                 sendResponseOK(cliInd);
00303                 return;
00304         }
00305         sendResponseBadRequest(cliInd);
00306 }
00307 
00308 void cmdHello(struct CommandHandler *ch, int cliInd)
00309 {
00310         sendResponseOK(cliInd);
00311 }
00312 
00313 int countInRole(enum RoleCode role)
00314 {
00315         int i, acc = 0;
00316         for (i = 0; i < clientCount; ++i)
00317                 if (role == clients[i].role)
00318                         acc += 1;
00319         return acc;
00320 }
00321 
00322 const char *stringifyRole(enum RoleCode role)
00323 {
00324         switch (role) {
00325                 case Unknown:
00326                         return "Unknown";
00327                         break;
00328                 case Display:
00329                         return "Display";
00330                         break;
00331                 case Controller:
00332                         return "Controller";
00333                         break;
00334                 case EEG:
00335                         return "EEG";
00336                         break;
00337                 default:
00338                         return "<error, unknown role>";
00339                         break;
00340         }
00341 }
00342 
00343 int makeNewClient(struct CommandHandler *ch, sock_t fd) {
00344         int myIndex = clientCount;
00345         clientCount += 1;
00346         memset(&clients[myIndex], 0, sizeof(clients[0]));
00347         clients[myIndex].fd = fd;
00348         clients[myIndex].role = Unknown;
00349         clients[myIndex].markedForDeletion = 0;
00350         clients[myIndex].linePos = 0;
00351         clients[myIndex].headerLen = 0;
00352         initInputBuffer(&clients[myIndex].ib);
00353         initOutputBuffer(&clients[myIndex].ob);
00354         newClientStarted(ch, myIndex);
00355         rtime(&clients[myIndex].lastAlive);
00356         return myIndex;
00357 }
00358 
00359 int main()
00360 {
00361   struct CommandHandler *ch;
00362 
00363         int i;
00364         sock_t mod_fd;
00365         int retval;
00366         sock_t sock_fd;
00367         fd_set toread, toerr;
00368   ch = newCommandHandler();
00369         rprintf("NSD (NeuroServer Daemon) v. %s-%s\n", VERSION, OSTYPESTR);
00370         enregisterCommand(ch, "hello", cmdHello);
00371         enregisterCommand(ch, "test", cmdHello);
00372         enregisterCommand(ch, "control", cmdControl);
00373         enregisterCommand(ch, "display", cmdDisplay);
00374         enregisterCommand(ch, "close", cmdClose);
00375         enregisterCommand(ch, "status", cmdStatus);
00376         enregisterCommand(ch, "role", cmdRole);
00377         enregisterCommand(ch, "eeg", cmdEEG);
00378         enregisterCommand(ch, "go", cmdgo);
00379         enregisterCommand(ch, "nogo", cmdnogo);
00380         enregisterCommand(ch, "setheader", cmdSetHeader);
00381         enregisterCommand(ch, "getheader", cmdGetHeader);
00382         enregisterCommand(ch, "!", cmdDataFrame);
00383         enregisterCommand(ch, "watch", cmdWatch);
00384         enregisterCommand(ch, "unwatch", cmdUnwatch);
00385         rinitNetworking();
00386         sock_fd = rsocket();
00387 
00388         updateMaxFd(sock_fd);
00389 
00390         rprintf("Binding network socket at %d\n", DEFAULTPORT); 
00391 
00392         retval = rbindAll(sock_fd);
00393         if (retval != 0) {
00394                 rprintf("bind error\n");
00395                 rexit(1);
00396         }
00397         rprintf("Socket bound.\n");
00398 
00399         rprintf("Please start your eeg driver (e.g. modeegdriver). \n");
00400 
00401         for (;;) {
00402                 time_t now;
00403                 rtime(&now);
00404                 for (i = 0; i < clientCount;) {
00405                         if (clients[i].markedForDeletion || now > clients[i].lastAlive + TIMEOUT){
00406                                 rprintf("Shutting down client %d\n", i);
00407                                 rshutdown(clients[i].fd);
00408                                 if (clients[i].role == Display) {  // Remove all watchers
00409                                         int j;
00410                                         for (j = 0; j < clientCount; j++) {
00411                                                 if (clients[j].role == EEG)
00412                                                         clients[j].isDisplaying[i] = 0;
00413                                         }
00414                                 }
00415                                 if (i != clientCount - 1)   // Move clients array down as a chunk
00416                                         memmove((char *) (&clients[i]), (char *) (&clients[i+1]), (clientCount - i - 1)*sizeof(clients[0]));
00417                                 clientCount -= 1;
00418                         }
00419                         else
00420                                 i += 1;
00421                 }
00422                 FD_ZERO(&toread);
00423                 FD_SET(sock_fd, &toread);
00424                 for (i = 0; i < clientCount; ++i) {
00425                         FD_SET(clients[i].fd, &toread);
00426                 }
00427                 toerr = toread;
00428                 retval = rselect(max_fd, &toread, NULL, &toerr);
00429 //              rprintf("Just selected, with retval %d\n", retval);
00430                 if (FD_ISSET(sock_fd, &toread)) {
00431                         int myIndex;
00432                         rprintf("Accepting from %p\n", sock_fd);
00433                         mod_fd = raccept(sock_fd);
00434                         updateMaxFd(mod_fd);
00435                         myIndex = makeNewClient(ch, mod_fd);
00436                         rprintf("Got connection on client %d.\n", myIndex);
00437                         continue;
00438                 }
00439                 for (i = 0; i < clientCount; ++i) {
00440                         if (FD_ISSET(clients[i].fd, &toerr)) {
00441                                 rprintf("Got error condition on %d\n", i);
00442                         }
00443                         if (!inputBufferEmpty(&clients[i].ib) || FD_ISSET(clients[i].fd, &toread)) {
00444                                 int j;
00445                                 do {
00446 //                                      rprintf("About to read for client %d and linePos %d\n", i, clients[i].linePos);
00447                                         j = my_read(clients[i].fd, clients[i].lineBuf+clients[i].linePos, MAXLEN - clients[i].linePos, &clients[i].ib);
00448                                         if (isEOF(clients[i].fd, &clients[i].ib)) {
00449                                                 clients[i].markedForDeletion = 1;
00450                                                 rprintf("Got EOF from client %d\n", i);
00451                                                 break;
00452                                         }
00453                                         if (j <= 0)
00454                                                 continue;
00455                                         if (j > 0) {
00456                                                 char *curPtr, *nlPtr;
00457                                                 curPtr = clients[i].lineBuf;
00458                                                 clients[i].linePos += j;
00459                                                 clients[i].lineBuf[clients[i].linePos] = '\0';
00460                                                 while ( (nlPtr = strchr(curPtr, '\n')) ) {
00461                                                         *nlPtr = '\0';
00462                                                         lineBuf = curPtr;
00463                                                         handleLine(ch, curPtr, i);
00464                                                         curPtr = nlPtr + 1;
00465                                                 }
00466                                                 memmove(clients[i].lineBuf, curPtr, strlen(curPtr)+1);
00467                                                 clients[i].linePos -= curPtr - clients[i].lineBuf;
00468                                                 rtime(&clients[i].lastAlive);
00469                                         }
00470                                 } while (!inputBufferEmpty(&clients[i].ib));
00471                         }
00472                 }
00473         }
00474         
00475         return 0;
00476 }
00477 

Generated on Tue Feb 8 00:05:16 2005 for Neuroserver by doxygen 1.3.3