3 #include "log.h" |
3 #include "log.h" |
4 |
4 |
5 #include <stdlib.h> |
5 #include <stdlib.h> |
6 #include <sys/types.h> |
6 #include <sys/types.h> |
7 #include <sys/socket.h> |
7 #include <sys/socket.h> |
8 #include <unistd.h> |
|
9 #include <fcntl.h> |
|
10 #include <string.h> |
8 #include <string.h> |
11 #include <assert.h> |
9 |
12 |
10 static void sock_tcp_release (struct sock_stream *base_sock) |
13 /* |
|
14 * Our basic socket event handler for driving our callbacks |
|
15 */ |
|
16 static void sock_tcp_event_handler (evutil_socket_t fd, short what, void *arg) |
|
17 { |
|
18 struct sock_tcp *sock = arg; |
|
19 |
|
20 (void) fd; |
|
21 |
|
22 // invoke appropriate callback |
|
23 sock_stream_invoke_callbacks(SOCK_TCP_BASE(sock), what); |
|
24 } |
|
25 |
|
26 /* |
|
27 * Our sock_stream_methods.read method |
|
28 */ |
|
29 static err_t sock_tcp_read (struct sock_stream *base_sock, void *buf, size_t *len) |
|
30 { |
11 { |
31 struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp); |
12 struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp); |
32 int ret; |
|
33 |
|
34 // read(), and detect non-EAGAIN or EOF |
|
35 if ((ret = read(sock->fd, buf, *len)) < 0 && errno != EAGAIN) |
|
36 // unexpected error |
|
37 RETURN_SET_ERROR_ERRNO(SOCK_TCP_ERR(sock), ERR_READ); |
|
38 |
|
39 else if (ret == 0) |
|
40 // EOF |
|
41 return SET_ERROR(SOCK_TCP_ERR(sock), ERR_READ_EOF); |
|
42 |
|
43 |
|
44 if (ret < 0) { |
|
45 // EAGAIN -> zero bytes |
|
46 *len = 0; |
|
47 |
|
48 } else { |
|
49 // normal -> bytes read |
|
50 *len = ret; |
|
51 } |
|
52 |
|
53 // ok |
|
54 return SUCCESS; |
|
55 } |
|
56 |
|
57 /* |
|
58 * Our sock_stream_methods.write method |
|
59 */ |
|
60 static err_t sock_tcp_write (struct sock_stream *base_sock, const void *buf, size_t *len) |
|
61 { |
|
62 struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp); |
|
63 int ret; |
|
64 |
|
65 // write(), and detect non-EAGAIN or EOF |
|
66 if ((ret = write(sock->fd, buf, *len)) < 0 && errno != EAGAIN) |
|
67 // unexpected error |
|
68 RETURN_SET_ERROR_ERRNO(SOCK_TCP_ERR(sock), ERR_WRITE); |
|
69 |
|
70 else if (ret == 0) |
|
71 // EOF |
|
72 return SET_ERROR(SOCK_TCP_ERR(sock), ERR_WRITE_EOF); |
|
73 |
|
74 |
|
75 if (ret < 0) { |
|
76 // EAGAIN -> zero bytes |
|
77 *len = 0; |
|
78 |
|
79 } else { |
|
80 // normal -> bytes read |
|
81 *len = ret; |
|
82 } |
|
83 |
|
84 return SUCCESS; |
|
85 } |
|
86 |
|
87 static err_t sock_tcp_event_init (struct sock_stream *base_sock) |
|
88 { |
|
89 struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp); |
|
90 err_t err; |
|
91 |
|
92 // set nonblocking |
|
93 if ((err = sock_tcp_set_nonblock(sock, 1))) |
|
94 return err; |
|
95 |
|
96 // add ourselves as the event handler |
|
97 if ((err = sock_tcp_init_ev(sock, &sock_tcp_event_handler, sock))) |
|
98 return err; |
|
99 |
|
100 // done |
|
101 return SUCCESS; |
|
102 } |
|
103 |
|
104 static err_t sock_tcp_event_enable (struct sock_stream *base_sock, short mask) |
|
105 { |
|
106 struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp); |
|
107 |
|
108 // implemented in sock_tcp_add_event |
|
109 return sock_tcp_add_event(sock, mask); |
|
110 } |
|
111 |
|
112 static void sock_tcp_release (struct sock_stream *base_sock) |
|
113 { |
|
114 struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp); |
|
115 |
13 |
116 // close and free |
14 // close and free |
117 sock_tcp_close(sock); |
15 sock_fd_close(SOCK_TCP_FD(sock)); |
118 sock_tcp_free(sock); |
16 sock_tcp_free(sock); |
119 } |
17 } |
120 |
18 |
121 /* |
19 /* |
122 * Our sock_stream_type |
20 * Our sock_stream_type |
123 */ |
21 */ |
124 static struct sock_stream_type sock_tcp_type = { |
22 static struct sock_stream_type sock_tcp_type = { |
125 .methods = { |
23 .methods = { |
126 .read = &sock_tcp_read, |
24 .read = &sock_fd_read, |
127 .write = &sock_tcp_write, |
25 .write = &sock_fd_write, |
128 .event_init = &sock_tcp_event_init, |
26 .event_init = &sock_fd_event_init, |
129 .event_enable = &sock_tcp_event_enable, |
27 .event_enable = &sock_fd_event_enable, |
130 .release = &sock_tcp_release, |
28 .release = &sock_tcp_release, |
131 }, |
29 }, |
132 }; |
30 }; |
133 |
31 |
134 err_t sock_tcp_alloc (struct sock_tcp **sock_ptr) |
32 static err_t sock_tcp_alloc (struct sock_tcp **sock_ptr) |
135 { |
33 { |
136 // alloc |
34 // alloc |
137 if ((*sock_ptr = calloc(1, sizeof(**sock_ptr))) == NULL) |
35 if ((*sock_ptr = calloc(1, sizeof(**sock_ptr))) == NULL) |
138 return ERR_CALLOC; |
36 return ERR_CALLOC; |
139 |
37 |
140 // initialize base with sock_tcp_type |
38 // initialize base with sock_tcp_type |
141 sock_stream_init(SOCK_TCP_BASE(*sock_ptr), &sock_tcp_type); |
39 sock_stream_init(SOCK_TCP_BASE(*sock_ptr), &sock_tcp_type); |
142 |
40 |
143 // invalid fds are <0 |
41 // init without any fd |
144 (*sock_ptr)->fd = -1; |
42 sock_fd_init(SOCK_TCP_FD(*sock_ptr), -1); |
145 |
43 |
146 // done |
44 // done |
147 return SUCCESS; |
45 return SUCCESS; |
148 } |
46 } |
149 |
47 |
150 err_t sock_tcp_init_fd (struct sock_tcp *sock, int fd) |
48 err_t sock_tcp_init_socket (struct sock_tcp *sock, struct addrinfo *addr, struct error_info *err) |
151 { |
49 { |
152 // valid fd |
50 int fd; |
153 assert(fd >= 0); |
51 |
154 |
52 // call socket |
155 // initialize |
53 if ((fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) < 0) |
156 sock->fd = fd; |
54 RETURN_SET_ERROR_ERRNO(err, ERR_SOCKET); |
157 |
|
158 // done |
|
159 return SUCCESS; |
|
160 } |
|
161 |
|
162 err_t sock_tcp_init_ev (struct sock_tcp *sock, void (*ev_cb)(evutil_socket_t, short, void *), void *cb_arg) |
|
163 { |
|
164 // require valid fd |
|
165 assert(sock->fd >= 0); |
|
166 |
|
167 // this is initialization |
|
168 assert(sock->ev_read == NULL && sock->ev_write == NULL); |
|
169 |
|
170 // create new event |
|
171 if ((sock->ev_read = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_READ, ev_cb, cb_arg)) == NULL) |
|
172 return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_NEW); |
|
173 |
|
174 if ((sock->ev_write = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_WRITE, ev_cb, cb_arg)) == NULL) |
|
175 return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_NEW); |
|
176 |
55 |
177 // ok |
56 // ok |
178 return SUCCESS; |
57 sock_fd_init(SOCK_TCP_FD(sock), fd); |
179 } |
58 |
180 |
|
181 void sock_tcp_deinit_ev (struct sock_tcp *sock) |
|
182 { |
|
183 if (sock->ev_read) { |
|
184 event_free(sock->ev_read); |
|
185 |
|
186 sock->ev_read = NULL; |
|
187 } |
|
188 |
|
189 if (sock->ev_write) { |
|
190 event_free(sock->ev_write); |
|
191 |
|
192 sock->ev_write = NULL; |
|
193 } |
|
194 } |
|
195 |
|
196 err_t sock_tcp_init_socket (struct sock_tcp *sock, struct addrinfo *addr, struct error_info *err) |
|
197 { |
|
198 // must not be set already |
|
199 assert(sock->fd < 0); |
|
200 |
|
201 // call socket |
|
202 if ((sock->fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) < 0) |
|
203 RETURN_SET_ERROR_ERRNO(err, ERR_SOCKET); |
|
204 |
|
205 // ok |
|
206 return SUCCESS; |
|
207 } |
|
208 |
|
209 err_t sock_tcp_add_event (struct sock_tcp *sock, short mask) |
|
210 { |
|
211 // just add the appropraite events |
|
212 if (mask & EV_READ && event_add(sock->ev_read, NULL)) |
|
213 return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_ADD); |
|
214 |
|
215 if (mask & EV_WRITE && event_add(sock->ev_write, NULL)) |
|
216 return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_ADD); |
|
217 |
|
218 // done |
|
219 return SUCCESS; |
59 return SUCCESS; |
220 } |
60 } |
221 |
61 |
222 /** |
62 /** |
223 * Attempt to connect to the given addrinfo, or the next one, if that fails, etc. |
63 * Attempt to connect to the given addrinfo, or the next one, if that fails, etc. |
322 // first, create the socket |
164 // first, create the socket |
323 if (sock_tcp_init_socket(sock, addr, err)) |
165 if (sock_tcp_init_socket(sock, addr, err)) |
324 return ERROR_CODE(err); |
166 return ERROR_CODE(err); |
325 |
167 |
326 // then, set it up as nonblocking |
168 // then, set it up as nonblocking |
327 if ((ERROR_CODE(err) = sock_tcp_set_nonblock(sock, true))) |
169 if ((ERROR_CODE(err) = sock_fd_set_nonblock(SOCK_TCP_FD(sock), true))) |
328 goto error; |
170 goto error; |
329 |
171 |
330 // then, initiate the connect |
172 // then, initiate the connect |
331 if ((ret = connect(sock->fd, addr->ai_addr, addr->ai_addrlen)) < 0 && errno != EINPROGRESS) |
173 if ((ret = connect(SOCK_TCP_FD(sock)->fd, addr->ai_addr, addr->ai_addrlen)) < 0 && errno != EINPROGRESS) |
332 JUMP_SET_ERROR_ERRNO(err, ERR_CONNECT); |
174 JUMP_SET_ERROR_ERRNO(err, ERR_CONNECT); |
333 |
175 |
334 if (ret < 0) { |
176 if (ret < 0) { |
335 // ok, connect started, setup our completion callback |
177 // ok, connect started, setup our completion callback |
336 if ((ERROR_CODE(err) = sock_tcp_init_ev(sock, &sock_tcp_connect_cb, sock))) |
178 if ((ERROR_CODE(err) = sock_fd_init_ev(SOCK_TCP_FD(sock), &sock_tcp_connect_cb, sock))) |
337 goto error; |
179 goto error; |
338 |
180 |
339 // enable for write |
181 // enable for write |
340 if ((ERROR_CODE(err) = sock_tcp_add_event(sock, EV_WRITE))) |
182 if ((ERROR_CODE(err) = sock_fd_enable_events(SOCK_TCP_FD(sock), EV_WRITE))) |
341 goto error; |
183 goto error; |
342 |
184 |
343 // set the "current" address in case it fails and we need to try the next one |
185 // set the "current" address in case it fails and we need to try the next one |
344 sock->async_cur = addr; |
186 sock->async_cur = addr; |
345 |
187 |
396 RETURN_SET_ERROR_EXTRA(err, ERR_GETADDRINFO, ret); |
251 RETURN_SET_ERROR_EXTRA(err, ERR_GETADDRINFO, ret); |
397 |
252 |
398 // try each result in turn |
253 // try each result in turn |
399 for (r = res; r; r = r->ai_next) { |
254 for (r = res; r; r = r->ai_next) { |
400 // create the socket |
255 // create the socket |
401 if ((sock->fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) < 0) { |
256 if ((SOCK_TCP_FD(sock)->fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) < 0) { |
402 // remember error |
257 // remember error |
403 SET_ERROR_ERRNO(err, ERR_SOCKET); |
258 SET_ERROR_ERRNO(err, ERR_SOCKET); |
404 |
259 |
405 // skip to next one |
260 // skip to next one |
406 continue; |
261 continue; |
407 } |
262 } |
408 |
263 |
409 // connect to remote address |
264 // connect to remote address |
410 if (connect(sock->fd, r->ai_addr, r->ai_addrlen)) { |
265 if (connect(SOCK_TCP_FD(sock)->fd, r->ai_addr, r->ai_addrlen)) { |
411 // remember error |
266 // remember error |
412 SET_ERROR_ERRNO(err, ERR_CONNECT); |
267 SET_ERROR_ERRNO(err, ERR_CONNECT); |
413 |
268 |
414 // close/invalidate socket |
269 // close/invalidate socket |
415 close(sock->fd); |
270 sock_fd_close(SOCK_TCP_FD(sock)); |
416 sock->fd = -1; |
|
417 |
271 |
418 // skip to next one |
272 // skip to next one |
419 continue; |
273 continue; |
420 } |
274 } |
421 |
275 |
422 // valid socket, use this |
276 // valid socket, use this |
423 break; |
277 break; |
424 } |
278 } |
425 |
279 |
426 // ensure we got some valid socket, else return last error code |
280 // ensure we got some valid socket, else return last error code |
427 if (sock->fd < 0) { |
281 if (SOCK_TCP_FD(sock)->fd < 0) { |
428 // did we hit some error? |
282 // did we hit some error? |
429 if (IS_ERROR(err)) |
283 if (IS_ERROR(err)) |
430 // return last error |
284 // return last error |
431 return ERROR_CODE(err); |
285 return ERROR_CODE(err); |
432 |
286 |
433 else |
287 else |
434 // no results |
288 // no results |
435 return SET_ERROR(err, ERR_GETADDRINFO_EMPTY); |
289 return SET_ERROR(err, ERR_GETADDRINFO_EMPTY); |
436 } |
290 } |
437 |
291 |
438 // ok, done |
292 // ok, done |
439 return 0; |
293 return 0; |
440 } |
294 } |
441 |
295 |
442 err_t sock_tcp_set_nonblock (struct sock_tcp *sock, bool nonblock) |
|
443 { |
|
444 // fcntl it |
|
445 // XXX: maintain old flags? |
|
446 if (fcntl(sock->fd, F_SETFL, nonblock ? O_NONBLOCK : 0) < 0) |
|
447 RETURN_SET_ERROR_ERRNO(SOCK_TCP_ERR(sock), ERR_FCNTL); |
|
448 |
|
449 // ok |
|
450 return SUCCESS; |
|
451 } |
|
452 |
|
453 err_t sock_tcp_close (struct sock_tcp *sock) |
|
454 { |
|
455 struct error_info *err = SOCK_TCP_ERR(sock); |
|
456 |
|
457 // no errors yet |
|
458 RESET_ERROR(err); |
|
459 |
|
460 // must be connected |
|
461 assert(sock->fd >= 0); |
|
462 |
|
463 // kill any events |
|
464 sock_tcp_deinit_ev(sock); |
|
465 |
|
466 // close the socket itself |
|
467 if (close(sock->fd)) |
|
468 SET_ERROR_ERRNO(err, ERR_CLOSE); |
|
469 |
|
470 // invalidate |
|
471 sock->fd = -1; |
|
472 |
|
473 return ERROR_CODE(err); |
|
474 } |
|
475 |
|
476 void sock_tcp_free (struct sock_tcp *sock) |
296 void sock_tcp_free (struct sock_tcp *sock) |
477 { |
297 { |
478 // must not be connected |
|
479 assert(sock->fd < 0); |
|
480 |
|
481 // free |
298 // free |
482 free(sock); |
299 free(sock); |
483 } |
300 } |
484 |
301 |
485 err_t sock_tcp_connect (struct sock_stream **sock_ptr, const char *host, const char *service, struct error_info *err) |
302 err_t sock_tcp_connect (struct sock_stream **sock_ptr, const char *host, const char *service, struct error_info *err) |