diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-16 07:06:31 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-16 07:06:31 +0000 |
commit | 89f3ecf7820857f91c4039536d2bbe3cf12d5f95 (patch) | |
tree | 76e6cc9ff403a8c5ee52448d7ae9311bdf499039 /src/usocket.c | |
parent | 3febb302ad28fd25de51cbc686739469b92d8921 (diff) | |
download | luasocket-89f3ecf7820857f91c4039536d2bbe3cf12d5f95.tar.gz luasocket-89f3ecf7820857f91c4039536d2bbe3cf12d5f95.tar.bz2 luasocket-89f3ecf7820857f91c4039536d2bbe3cf12d5f95.zip |
http.lua updated. still needs proxy support.
code.lua updated. looks neat.
Diffstat (limited to 'src/usocket.c')
-rw-r--r-- | src/usocket.c | 110 |
1 files changed, 65 insertions, 45 deletions
diff --git a/src/usocket.c b/src/usocket.c index b120d7b..f2d9f01 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
@@ -73,6 +73,14 @@ void sock_listen(p_sock ps, int backlog) | |||
73 | } | 73 | } |
74 | 74 | ||
75 | /*-------------------------------------------------------------------------*\ | 75 | /*-------------------------------------------------------------------------*\ |
76 | * | ||
77 | \*-------------------------------------------------------------------------*/ | ||
78 | void sock_shutdown(p_sock ps, int how) | ||
79 | { | ||
80 | shutdown(*ps, how); | ||
81 | } | ||
82 | |||
83 | /*-------------------------------------------------------------------------*\ | ||
76 | * Accept with timeout | 84 | * Accept with timeout |
77 | \*-------------------------------------------------------------------------*/ | 85 | \*-------------------------------------------------------------------------*/ |
78 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | 86 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, |
@@ -100,39 +108,47 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | |||
100 | 108 | ||
101 | /*-------------------------------------------------------------------------*\ | 109 | /*-------------------------------------------------------------------------*\ |
102 | * Send with timeout | 110 | * Send with timeout |
111 | * Here we exchanged the order of the calls to write and select | ||
112 | * The idea is that the outer loop (whoever is calling sock_send) | ||
113 | * will call the function again if we didn't time out, so we can | ||
114 | * call write and then select only if it fails. | ||
115 | * Should speed things up! | ||
116 | * We are also treating EINTR and EPIPE errors. | ||
103 | \*-------------------------------------------------------------------------*/ | 117 | \*-------------------------------------------------------------------------*/ |
104 | int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | 118 | int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, |
105 | int timeout) | 119 | int timeout) |
106 | { | 120 | { |
107 | t_sock sock = *ps; | 121 | t_sock sock = *ps; |
108 | struct timeval tv; | 122 | ssize_t put; |
109 | fd_set fds; | ||
110 | ssize_t put = 0; | ||
111 | int err; | ||
112 | int ret; | 123 | int ret; |
124 | /* avoid making system calls on closed sockets */ | ||
113 | if (sock == SOCK_INVALID) return IO_CLOSED; | 125 | if (sock == SOCK_INVALID) return IO_CLOSED; |
114 | tv.tv_sec = timeout / 1000; | 126 | /* make sure we repeat in case the call was interrupted */ |
115 | tv.tv_usec = (timeout % 1000) * 1000; | 127 | do put = write(sock, data, count); |
116 | FD_ZERO(&fds); | 128 | while (put <= 0 && errno == EINTR); |
117 | FD_SET(sock, &fds); | 129 | /* deal with failure */ |
118 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | 130 | if (put <= 0) { |
119 | if (ret > 0) { | 131 | /* in any case, nothing has been sent */ |
120 | put = write(sock, data, count); | ||
121 | if (put <= 0) { | ||
122 | err = IO_CLOSED; | ||
123 | #ifdef __CYGWIN__ | ||
124 | /* this is for CYGWIN, which is like Unix but has Win32 bugs */ | ||
125 | if (errno == EWOULDBLOCK) err = IO_DONE; | ||
126 | #endif | ||
127 | *sent = 0; | ||
128 | } else { | ||
129 | *sent = put; | ||
130 | err = IO_DONE; | ||
131 | } | ||
132 | return err; | ||
133 | } else { | ||
134 | *sent = 0; | 132 | *sent = 0; |
135 | return IO_TIMEOUT; | 133 | /* run select to avoid busy wait */ |
134 | if (errno != EPIPE) { | ||
135 | struct timeval tv; | ||
136 | fd_set fds; | ||
137 | tv.tv_sec = timeout / 1000; | ||
138 | tv.tv_usec = (timeout % 1000) * 1000; | ||
139 | FD_ZERO(&fds); | ||
140 | FD_SET(sock, &fds); | ||
141 | ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); | ||
142 | /* tell the caller to call us again because there is more data */ | ||
143 | if (ret > 0) return IO_DONE; | ||
144 | /* tell the caller there was no data before timeout */ | ||
145 | else return IO_TIMEOUT; | ||
146 | /* here we know the connection has been closed */ | ||
147 | } else return IO_CLOSED; | ||
148 | /* here we sent successfully sent something */ | ||
149 | } else { | ||
150 | *sent = put; | ||
151 | return IO_DONE; | ||
136 | } | 152 | } |
137 | } | 153 | } |
138 | 154 | ||
@@ -176,32 +192,36 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
176 | 192 | ||
177 | /*-------------------------------------------------------------------------*\ | 193 | /*-------------------------------------------------------------------------*\ |
178 | * Receive with timeout | 194 | * Receive with timeout |
195 | * Here we exchanged the order of the calls to write and select | ||
196 | * The idea is that the outer loop (whoever is calling sock_send) | ||
197 | * will call the function again if we didn't time out, so we can | ||
198 | * call write and then select only if it fails. | ||
199 | * Should speed things up! | ||
200 | * We are also treating EINTR errors. | ||
179 | \*-------------------------------------------------------------------------*/ | 201 | \*-------------------------------------------------------------------------*/ |
180 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | 202 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) |
181 | { | 203 | { |
182 | t_sock sock = *ps; | 204 | t_sock sock = *ps; |
183 | struct timeval tv; | 205 | ssize_t taken; |
184 | fd_set fds; | ||
185 | int ret; | ||
186 | ssize_t taken = 0; | ||
187 | if (sock == SOCK_INVALID) return IO_CLOSED; | 206 | if (sock == SOCK_INVALID) return IO_CLOSED; |
188 | tv.tv_sec = timeout / 1000; | 207 | do taken = read(sock, data, count); |
189 | tv.tv_usec = (timeout % 1000) * 1000; | 208 | while (taken <= 0 && errno == EINTR); |
190 | FD_ZERO(&fds); | 209 | if (taken <= 0) { |
191 | FD_SET(sock, &fds); | 210 | struct timeval tv; |
192 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | 211 | fd_set fds; |
193 | if (ret > 0) { | 212 | int ret; |
194 | taken = read(sock, data, count); | ||
195 | if (taken <= 0) { | ||
196 | *got = 0; | ||
197 | return IO_CLOSED; | ||
198 | } else { | ||
199 | *got = taken; | ||
200 | return IO_DONE; | ||
201 | } | ||
202 | } else { | ||
203 | *got = 0; | 213 | *got = 0; |
204 | return IO_TIMEOUT; | 214 | if (taken == 0) return IO_CLOSED; |
215 | tv.tv_sec = timeout / 1000; | ||
216 | tv.tv_usec = (timeout % 1000) * 1000; | ||
217 | FD_ZERO(&fds); | ||
218 | FD_SET(sock, &fds); | ||
219 | ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); | ||
220 | if (ret > 0) return IO_DONE; | ||
221 | else return IO_TIMEOUT; | ||
222 | } else { | ||
223 | *got = taken; | ||
224 | return IO_DONE; | ||
205 | } | 225 | } |
206 | } | 226 | } |
207 | 227 | ||