00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00087
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
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
00196
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
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
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;
00249 rprintf("Got header:\n");
00250 rprintf("The header is <%s>\n", hdr);
00251 readEDFString(&tmp, hdr, strlen(buf));
00252 makeREDFConfig(¤t, &tmp);
00253 clients[cliInd].headerLen = sizeof(clients[0].headerBuf);
00254 writeEDFString(¤t, 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) {
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)
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
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
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