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 | ||
