aboutsummaryrefslogtreecommitdiff
path: root/src/usocket.c
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-16 07:06:31 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-16 07:06:31 +0000
commit89f3ecf7820857f91c4039536d2bbe3cf12d5f95 (patch)
tree76e6cc9ff403a8c5ee52448d7ae9311bdf499039 /src/usocket.c
parent3febb302ad28fd25de51cbc686739469b92d8921 (diff)
downloadluasocket-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.c110
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\*-------------------------------------------------------------------------*/
78void 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\*-------------------------------------------------------------------------*/
78int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, 86int 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\*-------------------------------------------------------------------------*/
104int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, 118int 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\*-------------------------------------------------------------------------*/
180int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) 202int 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