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
00029
00030
00048 #include <xdas_base.h>
00049 #include <xdasd.h>
00050
00051 #include "xdasd_filter.h"
00052 #include "xdasd_event.h"
00053 #include "xdasd_list.h"
00054 #include "xdasd_net.h"
00055 #include "xdasd_log.h"
00056
00057 #include <malloc.h>
00058 #include <string.h>
00059 #include <errno.h>
00060 #include <stdio.h>
00061
00066 #ifdef _WIN32
00067 # define socklen_t int
00068 # define so_bool_t char
00069 # define BAD_SOCKET INVALID_SOCKET
00070
00071
00072 # define EWOULDBLOCK WSAEWOULDBLOCK
00073 # define EINPROGRESS WSAEINPROGRESS
00074 # define EALREADY WSAEALREADY
00075 # define ENOTSOCK WSAENOTSOCK
00076 # define EDESTADDRREQ WSAEDESTADDRREQ
00077 # define EMSGSIZE WSAEMSGSIZE
00078 # define EPROTOTYPE WSAEPROTOTYPE
00079 # define ENOPROTOOPT WSAENOPROTOOPT
00080 # define EPROTONOSUPPORT WSAEPROTONOSUPPORT
00081 # define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
00082 # define EOPNOTSUPP WSAEOPNOTSUPP
00083 # define EPFNOSUPPORT WSAEPFNOSUPPORT
00084 # define EAFNOSUPPORT WSAEAFNOSUPPORT
00085 # define EADDRINUSE WSAEADDRINUSE
00086 # define EADDRNOTAVAIL WSAEADDRNOTAVAIL
00087 # define ENETDOWN WSAENETDOWN
00088 # define ENETUNREACH WSAENETUNREACH
00089 # define ENETRESET WSAENETRESET
00090 # define ECONNABORTED WSAECONNABORTED
00091 # define ECONNRESET WSAECONNRESET
00092 # define ENOBUFS WSAENOBUFS
00093 # define EISCONN WSAEISCONN
00094 # define ENOTCONN WSAENOTCONN
00095 # define ESHUTDOWN WSAESHUTDOWN
00096 # define ETOOMANYREFS WSAETOOMANYREFS
00097 # define ETIMEDOUT WSAETIMEDOUT
00098 # define ECONNREFUSED WSAECONNREFUSED
00099 # define ELOOP WSAELOOP
00100 # define EHOSTDOWN WSAEHOSTDOWN
00101 # define EHOSTUNREACH WSAEHOSTUNREACH
00102 # define EREMOTE WSAEREMOTE
00103
00104 #else
00105 # include <sys/types.h>
00106 # include <sys/socket.h>
00107 # include <sys/un.h>
00108 # include <arpa/inet.h>
00109 # include <unistd.h>
00110 # include <fcntl.h>
00111 # define so_bool_t int
00112 # define BAD_SOCKET -1
00113 # define closesocket close
00114 #endif
00115
00119 #define SOCKET_UNUSED 0
00120 #define SOCKET_CLOSE 1
00121 #define SOCKET_LISTEN 2
00122 #define STREAM_READ_FIRST 3
00123 #define STREAM_READ 4
00124 #define STREAM_WRITE_FIRST 5
00125 #define STREAM_WRITE 6
00126
00127
00135 typedef struct XDASD_Socket_tag
00136 {
00137 XDLItem item;
00138 int state;
00139 sockfd_t fd;
00140 struct sockaddr_storage localaddr;
00141 struct sockaddr_storage peeraddr;
00142 xdas_buffer recvbuf;
00143 xdas_buffer sendbuf;
00144 } XDASD_Socket;
00145
00150 static XDList s_socklist = {0, 0, 0};
00151
00159 static XDASD_Socket * xdasd_socket_alloc(void)
00160 {
00161 XDASD_Socket * sock;
00162
00163 if ((sock = (XDASD_Socket *)malloc(sizeof(*sock))) != 0)
00164 {
00165 memset(sock, 0, sizeof(*sock));
00166 sock->fd = BAD_SOCKET;
00167 }
00168 return sock;
00169 }
00170
00178 static void xdasd_socket_free(XDASD_Socket * sock)
00179 {
00180 if (sock->fd != BAD_SOCKET)
00181 closesocket(sock->fd);
00182
00183 xdas_buffer_free(sock->recvbuf);
00184 xdas_buffer_free(sock->sendbuf);
00185
00186 free(sock);
00187 }
00188
00196 static int xdasd_socket_error(void)
00197 {
00198 #ifdef _WIN32
00199 return (int)WSAGetLastError();
00200 #else
00201 return errno;
00202 #endif
00203 }
00204
00214 static int xdasd_set_nonblocking(sockfd_t fd)
00215 {
00216 int err = 0;
00217 #ifdef _WIN32
00218 {
00219 u_long fdflags = 1;
00220 if ((err = ioctlsocket(fd, FIONBIO, &fdflags)) != 0)
00221 errno = WSAGetLastError();
00222 }
00223 #else
00224 {
00225 int fdflags = fcntl(fd, F_GETFL, 0);
00226 fcntl(fd, F_SETFL, fdflags | O_NONBLOCK);
00227 }
00228 #endif
00229 return err? -1: 0;
00230 }
00231
00243 static XDASD_Socket * xdasd_create_listen_socket(const char * ipcpath)
00244 {
00245 XDASD_Socket * sock;
00246
00247 if ((sock = xdasd_socket_alloc()) != 0)
00248 {
00249 struct sockaddr_storage ss;
00250 int addrsz = sizeof(ss);
00251
00252 memset(&ss, 0, sizeof(ss));
00253
00254 if (!ipcpath)
00255 {
00256 struct sockaddr_in * v4 = (struct sockaddr_in *)&ss;
00257 v4->sin_family = AF_INET;
00258 v4->sin_port = htons(XDASD_RESERVED_PORT);
00259 v4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
00260 addrsz = sizeof(*v4);
00261 }
00262 #ifndef _WIN32
00263 else
00264 {
00265 struct sockaddr_un * ud = (struct sockaddr_un *)&ss;
00266 ud->sun_family = AF_LOCAL;
00267 strncpy(ud->sun_path, ipcpath, sizeof(ud->sun_path) - 1);
00268 addrsz = sizeof(*ud);
00269 }
00270 #endif
00271
00272 if ((sock->fd = socket(ss.ss_family, SOCK_STREAM, 0)) != BAD_SOCKET)
00273 {
00274 so_bool_t reuse = 1;
00275
00276 setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR,
00277 (char *)&reuse, sizeof(reuse));
00278
00279 if (bind(sock->fd, (struct sockaddr *)&ss, addrsz) == 0)
00280 {
00281 if (listen(sock->fd, 5) == 0)
00282 {
00283 memcpy(&sock->localaddr, &ss, addrsz);
00284 xdasd_set_nonblocking(sock->fd);
00285 sock->state = SOCKET_LISTEN;
00286 return sock;
00287 }
00288 }
00289 }
00290 }
00291
00292
00293 if (sock)
00294 xdasd_socket_free(sock);
00295 return 0;
00296 }
00297
00305 static void xdasd_accept(XDASD_Socket * sock)
00306 {
00307 sockfd_t fd;
00308 XDASD_Socket * connsock;
00309 struct sockaddr_storage peeraddr;
00310 socklen_t peeraddrlen = sizeof(peeraddr);
00311
00312 if ((fd = accept(sock->fd, (struct sockaddr *)&peeraddr,
00313 &peeraddrlen)) != BAD_SOCKET)
00314 {
00315 xdasd_set_nonblocking(sock->fd);
00316 if ((connsock = xdasd_socket_alloc()) != 0)
00317 {
00318 connsock->fd = fd;
00319 memcpy(&connsock->peeraddr, &peeraddr, peeraddrlen);
00320 memcpy(&connsock->localaddr, &peeraddr, peeraddrlen);
00321 connsock->state = STREAM_READ_FIRST;
00322 xdasd_list_link_head(&s_socklist, &connsock->item);
00323 }
00324 }
00325 }
00326
00343 static int xdasd_net_dispatch(XDASD_Socket * sock)
00344 {
00345 static int (*handler_table[])(int*,xdas_buffer,xdas_buffer*) =
00346 {
00347 xdasd_event_process,
00348 xdasd_filter_process,
00349 };
00350
00351 size_t reqsz, rspsz;
00352 unsigned reqfn;
00353 int rspst, rspms = 0;
00354 xdas_buffer rsp, req = sock->recvbuf;
00355
00356 if ((rsp = xdas_buffer_realloc(sock->sendbuf, 12)) == 0)
00357 {
00359 return (errno = ENOMEM), -1;
00360 }
00361
00362
00363 rsp->curpos = rsp->start + 12;
00364
00365
00366 reqsz = xdas_buffer_get_uint32(req);
00367 if (req->end - req->curpos < 4 || (reqfn = xdas_buffer_get_uint32(req))
00368 >= xdas_elemcount(handler_table))
00369 {
00371 xdas_buffer_put_uint32(rsp, (unsigned)(rsp->curpos - rsp->start));
00372 xdas_buffer_put_uint32(rsp, XDAS_S_FAILURE);
00373 xdas_buffer_put_uint32(rsp, OXDAS_MS_PROTOCOL);
00374 sock->sendbuf = rsp;
00375 return 0;
00376 }
00377
00379
00380
00381
00382 rspst = handler_table[reqfn](&rspms, req, &rsp);
00383
00384
00385 rspsz = rsp->curpos - rsp->start;
00386 rsp->curpos = rsp->start;
00387 xdas_buffer_put_uint32(rsp, rspsz);
00388 xdas_buffer_put_uint32(rsp, rspst);
00389 xdas_buffer_put_uint32(rsp, rspms);
00390 sock->sendbuf = rsp;
00391
00393
00394
00395 return 0;
00396 }
00397
00405 static void xdasd_write_stream(XDASD_Socket * sock)
00406 {
00407 if (sock->state == STREAM_WRITE_FIRST)
00408 {
00409 sock->sendbuf->curpos = sock->sendbuf->start;
00410 sock->state = STREAM_WRITE;
00411 }
00412
00413
00414 if (sock->sendbuf->end - sock->sendbuf->start != 0)
00415 {
00416 int byteswritten, flags = 0;
00417 #ifdef MSG_DONTWAIT
00418 flags = MSG_DONTWAIT;
00419 #endif
00420 if ((byteswritten = send(sock->fd, (char *)sock->sendbuf->curpos,
00421 (int)(sock->sendbuf->end - sock->sendbuf->start), flags)) > 0)
00422 {
00423 sock->sendbuf->curpos += byteswritten;
00424 if (sock->sendbuf->curpos == sock->sendbuf->end)
00425 sock->state = STREAM_READ_FIRST;
00426 }
00427 else if (xdasd_socket_error() != EWOULDBLOCK)
00428 sock->state = SOCKET_CLOSE;
00429 }
00430 }
00431
00440 static void xdasd_read_stream(XDASD_Socket * sock)
00441 {
00442 int bytesread;
00443
00444 if (sock->state == STREAM_READ_FIRST)
00445 {
00446 xdas_buffer req;
00447 size_t msgsz;
00448 char peek[4];
00449
00450 if ((bytesread = recv(sock->fd, peek, sizeof(peek), MSG_PEEK)) <= 0)
00451 {
00452 sock->state = SOCKET_CLOSE;
00453 return;
00454 }
00455
00456 msgsz = AS_UINT32(peek);
00457 if (msgsz > MAX_XDAS_MSG_SIZE)
00458 {
00459 xdasd_log(0, "PROTOCOL_ERROR - message too large!\n");
00460 sock->state = SOCKET_CLOSE;
00461 return;
00462 }
00463 if ((req = xdas_buffer_realloc(sock->recvbuf, msgsz)) == 0)
00464 {
00465 xdasd_log(0, "INTERNAL_ERROR - out of memory!\n");
00466 sock->state = SOCKET_CLOSE;
00467 return;
00468 }
00469 req->curpos = req->start;
00470 sock->recvbuf = req;
00471 sock->state = STREAM_READ;
00472 }
00473
00474
00475 if ((bytesread = recv(sock->fd, (char *)sock->recvbuf->curpos,
00476 (int)(sock->recvbuf->end - sock->recvbuf->curpos), 0)) <= 0)
00477 {
00478 sock->state = SOCKET_CLOSE;
00479 return;
00480 }
00481
00482 sock->recvbuf->curpos += bytesread;
00483 if (sock->recvbuf->curpos == sock->recvbuf->end)
00484 {
00485
00486 sock->recvbuf->curpos = sock->recvbuf->start;
00487 if (xdasd_net_dispatch(sock) < 0)
00488 {
00489 sock->state = SOCKET_CLOSE;
00490 return;
00491 }
00492
00493 sock->state = STREAM_WRITE_FIRST;
00494 xdasd_write_stream(sock);
00495 }
00496 }
00497
00498
00499
00508 int xdasd_net_init(const char * ipcpath)
00509 {
00510 XDASD_Socket * sock;
00511
00512 #ifdef _WIN32
00513 {
00514 WORD vreq = MAKEWORD(2,2);
00515 WSADATA wsadata;
00516 if (WSAStartup(vreq, &wsadata) != 0)
00517 return -1;
00518 }
00519 #endif
00520
00521
00522 while (s_socklist.count)
00523 xdasd_socket_free((XDASD_Socket *)
00524 xdasd_list_unlink(&s_socklist, s_socklist.head));
00525
00526 #ifndef _WIN32
00527
00528 if ((sock = xdasd_create_listen_socket(ipcpath)) != 0)
00529 {
00530 xdasd_list_link_tail(&s_socklist, &sock->item);
00531 xdasd_log(0, "Listening on Unix domain socket...\n");
00532 }
00533 else
00534 xdasd_log(0, "NETWORK: Could not initialize Unix domain socket.\n");
00535 #else
00536 (void)ipcpath;
00537 #endif
00538
00539
00540 if ((sock = xdasd_create_listen_socket(0)) != 0)
00541 {
00542 xdasd_list_link_tail(&s_socklist, &sock->item);
00543 xdasd_log(0, "Listening on TCP socket...\n");
00544 }
00545 else
00546 xdasd_log(0, "NETWORK: Could not initialize TCP socket.\n");
00547
00548 #ifdef _WIN32
00549 if (!s_socklist.count)
00550 {
00551 errno = WSAGetLastError();
00552 WSACleanup();
00553 }
00554 #endif
00555
00556 return s_socklist.count? 0: -1;
00557 }
00558
00559 #ifdef _WIN32
00560 # pragma warning(push)
00561 # pragma warning(disable: 4127)
00562 #endif
00563
00572 void xdasd_net_load_fdsets(int * highfd, fd_set * readfds, fd_set * writefds)
00573 {
00574 XDASD_Socket * del = 0;
00575 XDASD_Socket * sock = (XDASD_Socket *)s_socklist.head;
00576
00577 while (sock)
00578 {
00579 if (sock->fd > (sockfd_t)*highfd)
00580 *highfd = (int)sock->fd;
00581
00582 switch(sock->state)
00583 {
00584 case SOCKET_LISTEN:
00585 FD_SET(sock->fd, readfds);
00586 break;
00587
00588 case STREAM_READ_FIRST:
00589 case STREAM_READ:
00590 FD_SET(sock->fd, readfds);
00591 break;
00592
00593 case STREAM_WRITE_FIRST:
00594 case STREAM_WRITE:
00595 FD_SET(sock->fd, writefds);
00596 break;
00597
00598 case SOCKET_CLOSE:
00599 del = sock;
00600 break;
00601 }
00602 sock = (XDASD_Socket *)sock->item.next;
00603 if (del)
00604 {
00605 xdasd_socket_free((XDASD_Socket *)
00606 xdasd_list_unlink(&s_socklist, (XDLItem *)del));
00607 del = 0;
00608 }
00609 }
00610 }
00611
00612 #ifdef _WIN32
00613 # pragma warning(pop)
00614 #endif
00615
00625 void xdasd_net_event_handler(int fdcount, fd_set * readfds, fd_set * writefds)
00626 {
00627 XDASD_Socket * sock = (XDASD_Socket *)s_socklist.head;
00628
00629 while (sock && fdcount)
00630 {
00631 if (FD_ISSET(sock->fd, readfds))
00632 {
00633 switch (sock->state)
00634 {
00635 case SOCKET_LISTEN:
00636 xdasd_accept(sock);
00637 break;
00638
00639 case STREAM_READ_FIRST:
00640 case STREAM_READ:
00641 xdasd_read_stream(sock);
00642 break;
00643
00644 }
00645 --fdcount;
00646 }
00647 else if (FD_ISSET(sock->fd, writefds))
00648 {
00649 switch (sock->state)
00650 {
00651 case STREAM_WRITE_FIRST:
00652 case STREAM_WRITE:
00653 xdasd_write_stream(sock);
00654 break;
00655 }
00656 --fdcount;
00657 }
00658 sock = (XDASD_Socket *)sock->item.next;
00659 }
00660 }
00661
00666 void xdasd_net_exit(void)
00667 {
00668 XDASD_Socket * sock = (XDASD_Socket *)s_socklist.head;
00669 while (sock)
00670 {
00671 XDASD_Socket * del = sock;
00672 sock = (XDASD_Socket *)sock->item.next;
00673 xdasd_socket_free(del);
00674 }
00675 s_socklist.head = s_socklist.tail = 0;
00676 s_socklist.count = 0;
00677
00678 #ifdef _WIN32
00679 WSACleanup();
00680 #endif
00681 }
00682