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

ns2net.c

Go to the documentation of this file.
00001 #include <malloc.h>
00002 #include <unistd.h>
00003 #include <stdio.h>
00004 #include <errno.h>
00005 #include <stdlib.h>
00006 #include <string.h>
00007 #include <nsnet.h>
00008 #include <fcntl.h>
00009 #include <assert.h>
00010 #include <neuro/neuro.h>
00011 #include <neuro/ns2net.h>
00012 
00013 struct NSNetConnectionController {
00014   struct NSNet *ns;
00015   void *udata;
00016   rsockaddr_t peer;
00017   sock_t fd;
00018 };
00019 
00020 struct NSNetReadHandlerInternal {
00021   struct NSNet *ns;
00022   sock_t fd;
00023   void *udata;
00024   struct NSNetConnectionReadHandler nsrh;
00025 };
00026 
00027 struct NSNetBindHandlerInternal {
00028   struct NSNet *ns;
00029   sock_t fd;
00030   void *udata;
00031   struct NSNetBindHandler nsb;
00032 };
00033 
00034 struct NSNetConnectionHandlerInternal {
00035   struct NSNet *ns;
00036   sock_t fd;
00037   void *udata;
00038   struct NSNetConnectionHandler nsc;
00039   rsockaddr_t dest;
00040   struct NSNetConnectionController nscc;
00041 };
00042 
00043 #define MAXCONN 256
00044 
00049 struct NSNet {
00050   sock_t max_fd;
00051   fd_set readfds, writefds, errfds;
00052   int NSCICount;
00053   struct StringTable *connectMap;
00054   struct StringTable *bindMap;
00055   struct StringTable *readerMap;
00056 };
00057 
00058 static void addWriteFd(struct NSNet *ns, sock_t fd);
00059 static void addReadFd(struct NSNet *ns, sock_t fd);
00060 static void addErrFd(struct NSNet *ns, sock_t fd);
00061 
00062 int attachConnectionReadHandler(struct NSNetConnectionController *nscc,
00063     const struct NSNetConnectionReadHandler *nscch, void *udata)
00064 {
00065   struct NSNet *ns;
00066   struct NSNetReadHandlerInternal *newReader;
00067   ns = nscc->ns;
00068   newReader = (struct NSNetReadHandlerInternal *)calloc(sizeof(*newReader),1);
00069   newReader->nsrh = *nscch;
00070   newReader->udata = udata;
00071   newReader->fd = nscc->fd;
00072   newReader->ns = ns;
00073   putInt(ns->readerMap, nscc->fd, newReader);
00074   addReadFd(ns, nscc->fd);
00075   return 0;
00076 }
00077 
00078 int attemptBind(struct NSNet *ns, const struct NSNetBindHandler *nsb,
00079                 int isLocalOnly, unsigned short portNum, void *udata)
00080 {
00081   struct NSNetBindHandlerInternal *bindHI;
00082 
00083   sock_t sock_fd;
00084   rsockaddr_t local;
00085   int retval;
00086   int one = 1;
00087 
00088   sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00089   if (sock_fd < 0) {
00090     perror("socket");
00091     nsb->error(udata);
00092     return 1;
00093   }
00094   retval = setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
00095 
00096   if (retval != 0) {
00097     perror("setsockopt");
00098     nsb->error(udata);
00099     return 1;
00100   }
00101 
00102   local.sin_family = AF_INET;
00103   local.sin_port = htons(portNum);
00104   if (isLocalOnly) {
00105     retval = inet_aton("127.0.0.1", &local.sin_addr);
00106     if (retval == 0) {
00107       perror("inet_aton");
00108       nsb->error(udata);
00109       return 1;
00110     }
00111   }
00112   else
00113     local.sin_addr.s_addr =  INADDR_ANY;
00114 
00115   retval = bind(sock_fd, (struct sockaddr *) &local, sizeof(local));
00116   if (retval != 0) {
00117     perror("bind");
00118     nsb->error(udata);
00119     return 1;
00120   }
00121   retval = listen(sock_fd, MAXCLIENTS);
00122   if (retval != 0) {
00123     perror("listen");
00124     nsb->error(udata);
00125     return 1;
00126   }
00127 
00128   addErrFd(ns, sock_fd);
00129   addReadFd(ns, sock_fd);
00130 
00131   bindHI = calloc(sizeof(*bindHI), 1);
00132   bindHI->fd = sock_fd;
00133   bindHI->udata = udata;
00134   bindHI->nsb = *nsb;
00135 
00136   putInt(ns->bindMap, sock_fd, bindHI);
00137 
00138   return 0;
00139 }
00140 
00141 int setNSnonblocking(struct NSNet *ns, sock_t sock_fd)
00142 {
00143   int flags, retval;
00144   flags = fcntl(sock_fd, F_GETFL, 0);
00145   retval = fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK);
00146   assert(retval == 0 && "Error setting O_NONBLOCK\n");
00147   return 0;
00148 }
00149 
00150 static void updateNSNetMaxFd(struct NSNet *ns, sock_t fd)
00151 {
00152   if (ns->max_fd < fd+1)
00153     ns->max_fd = fd+1;
00154 }
00155 
00156 /* Returns 0 on success 
00157  * \param name The hostname to connect to, or dotted quad
00158  * \param portNo The integer network port number to connect to
00159  * \param result The address of the rsockaddr_t that will receive the lookup
00160  * \param nsc The NSConnectionHandler that may be used for unknownHost messages
00161  * \param udata Only for use when an unknown host error occurs on callback
00162  *  This function returns 1 on unknown host failures.
00163  */
00164 static int makeAddress(const char *name, unsigned short portNo, rsockaddr_t *result, const struct NSNetConnectionHandler *nsc, void *udata)
00165 {
00166   hostent_t host;
00167   host = gethostbyname(name);
00168   if(host == NULL) {
00169     nsc->unknownHost(udata);
00170     return 1;
00171   }
00172   result->sin_family = AF_INET;
00173   result->sin_port = htons(portNo);
00174   result->sin_addr = *((struct in_addr *)host->h_addr);
00175   return 0;
00176 }
00177 
00178 static void addWriteFd(struct NSNet *ns, sock_t fd)
00179 {
00180   FD_SET(fd, &ns->writefds);
00181   updateNSNetMaxFd(ns, fd);
00182 }
00183 
00184 static void addErrFd(struct NSNet *ns, sock_t fd)
00185 {
00186   FD_SET(fd, &ns->errfds);
00187   updateNSNetMaxFd(ns, fd);
00188 }
00189 
00190 static void addReadFd(struct NSNet *ns, sock_t fd)
00191 {
00192   FD_SET(fd, &ns->readfds);
00193   updateNSNetMaxFd(ns, fd);
00194 }
00195 
00196 static void removeFdAll(struct NSNet *ns, sock_t fd)
00197 {
00198   FD_CLR(fd, &ns->readfds);
00199   FD_CLR(fd, &ns->writefds);
00200   FD_CLR(fd, &ns->errfds);
00201 }
00202 
00203 int attemptConnect(struct NSNet *ns, const struct NSNetConnectionHandler *nsc,
00204                     const char *destaddr, unsigned short destPort, void *udata)
00205 {
00206   int retval;
00207   int connErrno = 0;
00208   sock_t fd;
00209   rsockaddr_t dest;
00210   if (makeAddress(destaddr, destPort, &dest, nsc, udata)) {
00211     return 1;
00212   }
00213   fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00214   setNSnonblocking(ns, fd);
00215   errno = 0;
00216   retval = connect(fd, (struct sockaddr *) &dest, sizeof(dest));
00217   if (retval == -1) connErrno = errno;
00218   if (retval == 0) {
00219     struct NSNetConnectionController *nscc = calloc(sizeof(*nscc), 1);
00220     nscc->ns = ns;
00221     nscc->fd = fd;
00222     nscc->peer = dest;
00223     nscc->udata = udata;
00224     nsc->success(udata, nscc);
00225 
00226     return 0;
00227   }
00228   rassert(retval == -1);
00229   if (connErrno == EINPROGRESS) {
00230     struct NSNetConnectionHandlerInternal *connectHI;
00231     connectHI = calloc(sizeof(*connectHI), 1);
00232     connectHI->ns = ns;
00233     connectHI->nsc = *nsc;
00234     connectHI->fd = fd;
00235     connectHI->dest = dest;
00236     connectHI->udata = udata;
00237     addWriteFd(ns, fd);
00238     addErrFd(ns, fd);
00239     addReadFd(ns, fd);
00240     putInt(ns->connectMap, fd, connectHI);
00241     return 0;
00242   }
00243   rassert(0 && "Unkown connect error");
00244   return 1;
00245 }
00246 
00247 #if 0
00248 static char *showFD(sock_t fd, fd_set *readfds, fd_set *writefds, fd_set *errfds) {
00249   static char buf[16];
00250   buf[0] = 0;
00251   if (FD_ISSET(fd, readfds)) strcat(buf, "RE ");
00252   if (FD_ISSET(fd, writefds)) strcat(buf, "WR ");
00253   if (FD_ISSET(fd, errfds)) strcat(buf, "EX ");
00254   if (buf[0] != 0)
00255     buf[strlen(buf)-1] = 0;
00256   return buf;
00257 }
00258 #endif
00259 
00260 static void removeReadHandlerInternal(struct NSNet *ns, struct NSNetReadHandlerInternal *readHI)
00261 {
00262   delInt(ns->readerMap, readHI->fd);
00263   free(readHI);
00264 }
00265 
00266 static void removeConnectionHandlerInternal(struct NSNet *ns, struct NSNetConnectionHandlerInternal *connectHI)
00267 {
00268   removeFdAll(ns, connectHI->fd);
00269   delInt(ns->connectMap, connectHI->fd);
00270   free(connectHI);
00271 }
00272 
00273 void waitForNetEvent(struct NSNet *ns, int timeout)
00274 {
00275   fd_set readfds, writefds, errfds;
00276   sock_t max_fd;
00277   struct timeval tv;
00278   struct NSNetConnectionController *nscc;
00279   struct NSNetBindHandlerInternal *bindHI;
00280   struct NSNetConnectionHandlerInternal *connectHI;
00281   struct NSNetReadHandlerInternal *readerHI;
00282   int retval;
00283   int i;
00284   readfds = ns->readfds;
00285   writefds = ns->writefds;
00286   errfds = ns->errfds;
00287   max_fd = ns->max_fd;
00288   tv.tv_sec = timeout / 1000;
00289   tv.tv_usec = (timeout % 1000) * 1000;
00290   retval = select(max_fd, &readfds, &writefds, &errfds, &tv);
00291   if (retval > 0) 
00292   { // There are some fds ready
00293     int connErrno, connErrnoLen = sizeof(connErrno);
00294     for (i = 0; i < ns->max_fd; i+=1)
00295     {
00296       char buf[1024];
00297       if (FD_ISSET(i, &readfds) && (readerHI = findInt(ns->readerMap, i))) {
00298         int len = read(i, buf, 1024);
00299         if (len > 0)
00300           readerHI->nsrh.bytesRead(readerHI->udata, buf, len);
00301         if (len == 0) {
00302           close(i);
00303           readerHI->nsrh.closed(readerHI->udata);
00304           removeFdAll(ns, i);
00305           removeReadHandlerInternal(ns, readerHI);
00306         }
00307       }
00308       if (FD_ISSET(i, &readfds) && (bindHI = findInt(ns->bindMap, i))) {
00309         int addrlen = sizeof(nscc->peer);
00310         nscc = calloc(sizeof(*nscc), 1);
00311         nscc->ns = ns;
00312         nscc->udata = bindHI->udata;
00313         nscc->fd = accept(i, (struct sockaddr *) &nscc->peer, &addrlen);
00314         setNSnonblocking(ns, nscc->fd);
00315         bindHI->nsb.success(bindHI->udata, nscc);
00316       }
00317     }
00318     for (i = 0; i < ns->max_fd; i+= 1)
00319     {
00320       if ((FD_ISSET(i, &writefds) || FD_ISSET(i, &errfds) || FD_ISSET(i, &readfds)) && (connectHI = findInt(ns->connectMap, i)))
00321       {
00322         if (getsockopt(connectHI->fd, SOL_SOCKET, SO_ERROR, &connErrno, &connErrnoLen) == 0) 
00323         {
00324           switch(connErrno)
00325           {
00326             case ECONNREFUSED:
00327               connectHI->nsc.refused(connectHI->udata);
00328               removeConnectionHandlerInternal(ns, connectHI);
00329               break;
00330             case 0:
00331               nscc = calloc(sizeof(*nscc), 1);
00332               nscc->ns = ns;
00333               nscc->peer = connectHI->dest;
00334               nscc->fd = connectHI->fd;
00335               nscc->udata = connectHI->udata;
00336               removeConnectionHandlerInternal(ns, connectHI);
00337               connectHI->nsc.success(connectHI->udata, nscc);
00338               break;
00339             default:
00340               printf("Unhandled connErrno: %d\n", connErrno);
00341               exit(1);
00342               break;
00343           }
00344           return;
00345         }
00346       }
00347     }
00348   }
00349 }
00350 
00351 struct NSNet *newNSNet(void)
00352 {
00353   struct NSNet *result;
00354   result = calloc(sizeof(struct NSNet), 1);
00355   FD_ZERO(&result->readfds);
00356   FD_ZERO(&result->writefds);
00357   FD_ZERO(&result->errfds);
00358   result->bindMap = newStringTable();
00359   result->connectMap = newStringTable();
00360   result->readerMap = newStringTable();
00361   return result;
00362 }
00363 
00364 void closeNSNet(struct NSNet *ns)
00365 {
00366   freeStringTable(ns->bindMap);
00367   freeStringTable(ns->connectMap);
00368   freeStringTable(ns->readerMap);
00369   free(ns);
00370 }
00371 
00372 int closeConnection(struct NSNetConnectionController *nscc)
00373 {
00374    close(nscc->fd);
00375    return 0;
00376 }
00377 
00378 int writeNSBytes(struct NSNetConnectionController *nscc, void *buf, int len)
00379 {
00380   int writelen = 0;
00381   if (len > 0)
00382     writelen = write(nscc->fd, buf, len);
00383   return (writelen == len) ? 0 : 1;
00384 }
00385 
00386 

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