src/usocket.c

changeset 0
f7d2d78eb424
equal deleted inserted replaced
-1:000000000000 0:f7d2d78eb424
1 /*=========================================================================*\
2 * LuaSocket 2.0.2
3 * Copyright (C) 2004-2007 Diego Nehab
4 *
5 * Socket compatibilization module for Unix
6 *
7 * The code is now interrupt-safe.
8 * The penalty of calling select to avoid busy-wait is only paid when
9 * the I/O call fail in the first place.
10 *
11 * RCS ID: $Id: usocket.c,v 1.38 2007/10/13 23:55:20 diego Exp $
12 \*=========================================================================*/
13 #include <errno.h>
14 #include <sys/types.h>
15 #include <sys/time.h>
16 #include <sys/socket.h>
17 #include <string.h>
18 #include <signal.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21
22 #include "socket.h"
23 #include "usocket.h"
24
25 /*-------------------------------------------------------------------------*\
26 * Wait for readable/writable/connected socket with timeout
27 \*-------------------------------------------------------------------------*/
28 #ifdef SOCKET_POLL
29 int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
30 int ret;
31 struct pollfd pfd;
32 pfd.fd = *ps;
33 pfd.events = sw;
34 pfd.revents = 0;
35 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
36 do {
37 int t = (int)(timeout_getretry(tm)*1e3);
38 ret = poll(&pfd, 1, t >= 0? t: -1);
39 } while (ret == -1 && errno == EINTR);
40 if (ret == -1) return errno;
41 if (ret == 0) return IO_TIMEOUT;
42 if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED;
43 return IO_DONE;
44 }
45 #else
46 int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
47 int ret;
48 fd_set rfds, wfds, *rp, *wp;
49 struct timeval tv, *tp;
50 double t;
51 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
52 do {
53 /* must set bits within loop, because select may have modifed them */
54 rp = wp = NULL;
55 if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(*ps, &rfds); rp = &rfds; }
56 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
57 t = timeout_getretry(tm);
58 tp = NULL;
59 if (t >= 0.0) {
60 tv.tv_sec = (int)t;
61 tv.tv_usec = (int)((t-tv.tv_sec)*1.0e6);
62 tp = &tv;
63 }
64 ret = select(*ps+1, rp, wp, NULL, tp);
65 } while (ret == -1 && errno == EINTR);
66 if (ret == -1) return errno;
67 if (ret == 0) return IO_TIMEOUT;
68 if (sw == WAITFD_C && FD_ISSET(*ps, &rfds)) return IO_CLOSED;
69 return IO_DONE;
70 }
71 #endif
72
73
74 /*-------------------------------------------------------------------------*\
75 * Initializes module
76 \*-------------------------------------------------------------------------*/
77 int socket_open(void) {
78 /* instals a handler to ignore sigpipe or it will crash us */
79 signal(SIGPIPE, SIG_IGN);
80 return 1;
81 }
82
83 /*-------------------------------------------------------------------------*\
84 * Close module
85 \*-------------------------------------------------------------------------*/
86 int socket_close(void) {
87 return 1;
88 }
89
90 /*-------------------------------------------------------------------------*\
91 * Close and inutilize socket
92 \*-------------------------------------------------------------------------*/
93 void socket_destroy(p_socket ps) {
94 if (*ps != SOCKET_INVALID) {
95 socket_setblocking(ps);
96 close(*ps);
97 *ps = SOCKET_INVALID;
98 }
99 }
100
101 /*-------------------------------------------------------------------------*\
102 * Put socket into blocking mode
103 \*-------------------------------------------------------------------------*/
104 void socket_setblocking(p_socket ps) {
105 int flags = fcntl(*ps, F_GETFL, 0);
106 flags &= (~(O_NONBLOCK));
107 fcntl(*ps, F_SETFL, flags);
108 }
109
110 /*-------------------------------------------------------------------------*\
111 * Put socket into non-blocking mode
112 \*-------------------------------------------------------------------------*/
113 void socket_setnonblocking(p_socket ps) {
114 int flags = fcntl(*ps, F_GETFL, 0);
115 flags |= O_NONBLOCK;
116 fcntl(*ps, F_SETFL, flags);
117 }
118
119 /*-------------------------------------------------------------------------*\
120 * Error translation functions
121 * Make sure important error messages are standard
122 \*-------------------------------------------------------------------------*/
123 const char *socket_strerror(int err) {
124 if (err <= 0) return io_strerror(err);
125 switch (err) {
126 case EADDRINUSE: return "address already in use";
127 case EISCONN: return "already connected";
128 case EACCES: return "permission denied";
129 case ECONNREFUSED: return "connection refused";
130 case ECONNABORTED: return "closed";
131 case ECONNRESET: return "closed";
132 case EPIPE: return "closed";
133 case ETIMEDOUT: return "timeout";
134 default: return strerror(errno);
135 }
136 }
137
138 /*-------------------------------------------------------------------------*\
139 * Underline error code.
140 \*-------------------------------------------------------------------------*/
141 int socket_error()
142 {
143 return errno;
144 }
145

mercurial