Let users retry connection in case of error. Especially SSL error.
[elinks.git] / src / network / socket.c
blob4fc655d14d6ed371e1c11e74bbb76a84d2c26fd8
1 /* Sockets-o-matic */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <errno.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #ifdef HAVE_NETINET_IN_H
11 #include <netinet/in.h> /* OS/2 needs this after sys/types.h */
12 #endif
13 #ifdef HAVE_SYS_SOCKET_H
14 #include <sys/socket.h> /* OS/2 needs this after sys/types.h */
15 #endif
16 #ifdef HAVE_FCNTL_H
17 #include <fcntl.h> /* OS/2 needs this after sys/types.h */
18 #endif
19 #ifdef HAVE_UNISTD_H
20 #include <unistd.h>
21 #endif
22 #ifdef HAVE_WS2TCPIP_H
23 #include <ws2tcpip.h> /* socklen_t for MinGW */
24 #endif
26 #ifdef HAVE_GETIFADDRS
27 #ifdef HAVE_NETDB_H
28 #include <netdb.h>
29 #endif
30 #ifdef HAVE_NET_IF_H
31 #include <net/if.h>
32 #endif
33 #ifdef HAVE_IFADDRS_H
34 #include <ifaddrs.h> /* getifaddrs() */
35 #endif
36 #endif /* HAVE_GETIFADDRS */
38 #ifdef HAVE_ARPA_INET_H
39 #include <arpa/inet.h>
40 #endif
42 #include "elinks.h"
44 #include "config/options.h"
45 #include "main/select.h"
46 #include "network/connection.h"
47 #include "network/dns.h"
48 #include "network/socket.h"
49 #include "network/ssl/socket.h"
50 #include "osdep/osdep.h"
51 #include "osdep/getifaddrs.h"
52 #include "protocol/http/blacklist.h"
53 #include "protocol/protocol.h"
54 #include "protocol/uri.h"
55 #include "util/error.h"
56 #include "util/memory.h"
57 #include "util/string.h"
60 /* Holds information used during the connection establishing phase. */
61 struct connect_info {
62 struct sockaddr_storage *addr; /* Array of found addresses. */
63 int addrno; /* Number of found addresses. */
64 int triedno; /* Index of last tried address */
65 socket_connect_T done; /* Callback signaled when connected. */
66 void *dnsquery; /* Pointer to DNS query info. */
67 int port; /* Which port to bind to. */
68 int ip_family; /* If non-zero, force to IP version. */
69 struct uri *uri; /* For updating the blacklist. */
72 /** For detecting whether a struct socket has been deleted while a
73 * function was using it. */
74 struct socket_weak_ref {
75 LIST_HEAD(struct socket_weak_ref);
77 /** done_socket() resets this to NULL. */
78 struct socket *socket;
81 static INIT_LIST_OF(struct socket_weak_ref, socket_weak_refs);
83 /* To enable logging of tranfers, for debugging purposes. */
84 #if 0
86 #define DEBUG_TRANSFER_LOGFILE "/tmp/log"
88 static void
89 debug_transfer_log(unsigned char *data, int len)
91 int fd = open(DEBUG_TRANSFER_LOGFILE, O_WRONLY | O_APPEND | O_CREAT, 0622);
93 if (fd == -1) return;
95 set_bin(fd);
96 write(fd, data, len < 0 ? strlen(data) : len);
97 close(fd);
99 #undef DEBUG_TRANSFER_LOGFILE
101 #else
102 #define debug_transfer_log(data, len)
103 #endif
106 static struct connect_info *
107 init_connection_info(struct uri *uri, struct socket *socket,
108 socket_connect_T connect_done)
110 struct connect_info *connect_info = mem_calloc(1, sizeof(*connect_info));
112 if (!connect_info) return NULL;
114 connect_info->done = connect_done;
115 connect_info->port = get_uri_port(uri);
116 connect_info->ip_family = uri->ip_family;
117 connect_info->triedno = -1;
118 connect_info->addr = NULL;
119 connect_info->uri = get_uri_reference(uri);
121 return connect_info;
124 static void
125 done_connection_info(struct socket *socket)
127 struct connect_info *connect_info = socket->connect_info;
129 assert(socket->connect_info);
131 if (connect_info->dnsquery) kill_dns_request(&connect_info->dnsquery);
133 mem_free_if(connect_info->addr);
134 done_uri(connect_info->uri);
135 mem_free_set(&socket->connect_info, NULL);
138 struct socket *
139 init_socket(void *conn, struct socket_operations *ops)
141 struct socket *socket;
143 socket = mem_calloc(1, sizeof(*socket));
144 if (!socket) return NULL;
146 socket->fd = -1;
147 socket->conn = conn;
148 socket->ops = ops;
149 socket->verify = 1;
151 return socket;
154 void
155 done_socket(struct socket *socket)
157 struct socket_weak_ref *ref;
159 close_socket(socket);
161 if (socket->connect_info)
162 done_connection_info(socket);
164 mem_free_set(&socket->read_buffer, NULL);
165 mem_free_set(&socket->write_buffer, NULL);
167 foreach(ref, socket_weak_refs) {
168 if (ref->socket == socket)
169 ref->socket = NULL;
173 void
174 close_socket(struct socket *socket)
176 if (socket->fd == -1) return;
177 #ifdef CONFIG_SSL
178 if (socket->ssl) ssl_close(socket);
179 #endif
180 close(socket->fd);
181 clear_handlers(socket->fd);
182 socket->fd = -1;
185 void
186 dns_exception(struct socket *socket)
188 connect_socket(socket, connection_state(S_EXCEPT));
191 static void
192 exception(struct socket *socket)
194 socket->ops->retry(socket, connection_state(S_EXCEPT));
198 void
199 timeout_socket(struct socket *socket)
201 if (!socket->connect_info) {
202 socket->ops->retry(socket, connection_state(S_TIMEOUT));
203 return;
206 /* Is the DNS resolving still in progress? */
207 if (socket->connect_info->dnsquery) {
208 socket->ops->done(socket, connection_state(S_TIMEOUT));
209 return;
212 /* Try the next address, */
213 connect_socket(socket, connection_state(S_TIMEOUT));
215 /* Reset the timeout if connect_socket() started a new attempt
216 * to connect. */
217 if (socket->connect_info)
218 socket->ops->set_timeout(socket, connection_state(0));
222 /* DNS callback. */
223 static void
224 dns_found(struct socket *socket, struct sockaddr_storage *addr, int addrlen)
226 struct connect_info *connect_info = socket->connect_info;
227 int size;
229 if (!addr) {
230 socket->ops->done(socket, connection_state(S_NO_DNS));
231 return;
234 assert(connect_info);
236 size = sizeof(*addr) * addrlen;
238 connect_info->addr = mem_alloc(size);
239 if (!connect_info->addr) {
240 socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
241 return;
244 memcpy(connect_info->addr, addr, size);
245 connect_info->addrno = addrlen;
247 /* XXX: Passing non-result state here is bad but a lack of alternatives
248 * makes it so. Well adding get_state() socket operation could maybe fix
249 * it but the returned state would most likely be a non-result one at
250 * this point in the connection lifecycle. This will, however, only be a
251 * problem if connect_socket() fails without doing any system calls
252 * which is only the case when forcing the IP family. So it is better to
253 * handle it in connect_socket(). */
254 connect_socket(socket, connection_state(S_CONN));
257 void
258 make_connection(struct socket *socket, struct uri *uri,
259 socket_connect_T connect_done, int no_cache)
261 unsigned char *host = get_uri_string(uri, URI_DNS_HOST);
262 struct connect_info *connect_info;
263 enum dns_result result;
265 socket->ops->set_timeout(socket, connection_state(0));
267 if (!host) {
268 socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
269 return;
272 connect_info = init_connection_info(uri, socket, connect_done);
273 if (!connect_info) {
274 mem_free(host);
275 socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
276 return;
279 socket->connect_info = connect_info;
280 /* XXX: Keep here and not in init_connection_info() to make
281 * complete_connect_socket() work from the HTTP implementation. */
282 socket->need_ssl = get_protocol_need_ssl(uri->protocol);
283 if (!socket->set_no_tls) {
284 enum blacklist_flags flags = get_blacklist_flags(uri);
285 socket->no_tls = ((flags & SERVER_BLACKLIST_NO_TLS) != 0);
286 socket->set_no_tls = 1;
289 debug_transfer_log("\nCONNECTION: ", -1);
290 debug_transfer_log(host, -1);
291 debug_transfer_log("\n", -1);
293 result = find_host(host, &connect_info->dnsquery, (dns_callback_T) dns_found,
294 socket, no_cache);
296 mem_free(host);
298 if (result == DNS_ASYNC)
299 socket->ops->set_state(socket, connection_state(S_DNS));
303 /* Returns negative if error, otherwise pasv socket's fd. */
305 get_pasv_socket(struct socket *ctrl_socket, struct sockaddr_storage *addr)
307 struct sockaddr_in bind_addr4;
308 struct sockaddr *bind_addr;
309 struct sockaddr *pasv_addr = (struct sockaddr *) addr;
310 size_t addrlen;
311 int sock = -1;
312 int syspf; /* Protocol Family given to system, not EL_PF_... */
313 socklen_t len;
314 #ifdef CONFIG_IPV6
315 struct sockaddr_in6 bind_addr6;
317 if (ctrl_socket->protocol_family == EL_PF_INET6) {
318 bind_addr = (struct sockaddr *) &bind_addr6;
319 addrlen = sizeof(bind_addr6);
320 syspf = PF_INET6;
321 } else
322 #endif
324 bind_addr = (struct sockaddr *) &bind_addr4;
325 addrlen = sizeof(bind_addr4);
326 syspf = PF_INET;
329 memset(pasv_addr, 0, addrlen);
330 memset(bind_addr, 0, addrlen);
332 /* Get our endpoint of the control socket */
333 len = addrlen;
334 if (getsockname(ctrl_socket->fd, pasv_addr, &len)) {
335 sock_error:
336 if (sock != -1) close(sock);
337 ctrl_socket->ops->retry(ctrl_socket,
338 connection_state_for_errno(errno));
339 return -1;
342 /* Get a passive socket */
344 sock = socket(syspf, SOCK_STREAM, IPPROTO_TCP);
345 if (sock < 0)
346 goto sock_error;
348 /* Set it non-blocking */
350 if (set_nonblocking_fd(sock) < 0)
351 goto sock_error;
353 /* Bind it to some port */
355 memcpy(bind_addr, pasv_addr, addrlen);
356 #ifdef CONFIG_IPV6
357 if (ctrl_socket->protocol_family == EL_PF_INET6)
358 bind_addr6.sin6_port = 0;
359 else
360 #endif
361 bind_addr4.sin_port = 0;
363 if (bind(sock, bind_addr, addrlen))
364 goto sock_error;
366 /* Get our endpoint of the passive socket and save it to port */
368 len = addrlen;
369 if (getsockname(sock, pasv_addr, &len))
370 goto sock_error;
372 /* Go listen */
374 if (listen(sock, 1))
375 goto sock_error;
377 set_ip_tos_throughput(sock);
379 return sock;
382 #ifdef CONFIG_IPV6
383 static inline int
384 check_if_local_address6(struct sockaddr_in6 *addr)
386 struct ifaddrs *ifaddrs;
387 int local = IN6_IS_ADDR_LOOPBACK(&(addr->sin6_addr));
389 if (!local && !getifaddrs(&ifaddrs)) {
390 struct ifaddrs *ifa;
392 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
393 if (!ifa->ifa_addr)
394 continue;
396 if (ifa->ifa_addr->sa_family == AF_INET6
397 && !memcmp(&addr->sin6_addr.s6_addr,
398 &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr.s6_addr,
399 sizeof(addr->sin6_addr.s6_addr))) {
400 local = 1;
401 break;
404 if (ifa->ifa_addr->sa_family == AF_INET
405 && !memcmp(&((struct sockaddr_in *) &addr)->sin_addr.s_addr,
406 &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr,
407 sizeof(((struct sockaddr_in *) &addr)->sin_addr.s_addr))) {
408 local = 1;
409 break;
413 freeifaddrs(ifaddrs);
416 return local;
418 #endif /* CONFIG_IPV6 */
420 static inline int
421 check_if_local_address4(struct sockaddr_in *addr)
423 struct ifaddrs *ifaddrs;
424 int local = (ntohl(addr->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
426 if (!local && !getifaddrs(&ifaddrs)) {
427 struct ifaddrs *ifa;
429 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
430 if (!ifa->ifa_addr)
431 continue;
433 if (ifa->ifa_addr->sa_family != AF_INET) continue;
435 if (!memcmp(&addr->sin_addr.s_addr,
436 &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr,
437 sizeof(addr->sin_addr.s_addr))) {
438 local = 1;
439 break;
443 freeifaddrs(ifaddrs);
446 return local;
450 void
451 complete_connect_socket(struct socket *socket, struct uri *uri,
452 socket_connect_T done)
454 struct connect_info *connect_info = socket->connect_info;
456 if (connect_info && connect_info->uri) {
457 /* Remember whether the server supported TLS or not.
458 * Then the next request can immediately use the right
459 * protocol. This is important for HTTP POST requests
460 * because it is not safe to silently retry them. The
461 * uri parameter is normally NULL here so don't use it. */
462 if (socket->no_tls)
463 add_blacklist_entry(connect_info->uri,
464 SERVER_BLACKLIST_NO_TLS);
465 else
466 del_blacklist_entry(connect_info->uri,
467 SERVER_BLACKLIST_NO_TLS);
470 /* This is a special case used by the HTTP implementation to acquire an
471 * SSL link for handling CONNECT requests. */
472 if (!connect_info) {
473 assert(uri && socket);
474 connect_info = init_connection_info(uri, socket, done);
475 if (!connect_info) {
476 socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
477 return;
480 socket->connect_info = connect_info;
483 #ifdef CONFIG_SSL
484 /* Check if the connection should run over an encrypted link */
485 if (socket->need_ssl
486 && !socket->ssl
487 && ssl_connect(socket) < 0)
488 return;
489 #endif
491 if (connect_info->done)
492 connect_info->done(socket);
494 done_connection_info(socket);
497 /* Select handler which is set for the socket descriptor when connect() has
498 * indicated (via errno) that it is in progress. On completion this handler gets
499 * called. */
500 static void
501 connected(struct socket *socket)
503 int err = 0;
504 struct connection_state state = connection_state(0);
505 socklen_t len = sizeof(err);
507 assertm(socket->connect_info != NULL, "Lost connect_info!");
508 if_assert_failed return;
510 if (getsockopt(socket->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) == 0) {
511 /* Why does EMX return so large values? */
512 if (err >= 10000) err -= 10000;
513 if (err != 0)
514 state = connection_state_for_errno(err);
515 else
516 state = connection_state(0);
517 } else {
518 /* getsockopt() failed */
519 if (errno != 0)
520 state = connection_state_for_errno(errno);
521 else
522 state = connection_state(S_STATE);
525 if (!is_in_state(state, 0)) {
526 /* There are maybe still some more candidates. */
527 connect_socket(socket, state);
528 return;
531 complete_connect_socket(socket, NULL, NULL);
534 void
535 connect_socket(struct socket *csocket, struct connection_state state)
537 int sock = -1;
538 struct connect_info *connect_info = csocket->connect_info;
539 int i;
540 int trno = connect_info->triedno;
541 int only_local = get_cmd_opt_bool("localhost");
542 int saved_errno = 0;
543 int at_least_one_remote_ip = 0;
544 #ifdef CONFIG_IPV6
545 int try_ipv6 = get_opt_bool("connection.try_ipv6", NULL);
546 #endif
547 int try_ipv4 = get_opt_bool("connection.try_ipv4", NULL);
548 /* We tried something but we failed in such a way that we would rather
549 * prefer the connection to retain the information about previous
550 * failures. That is, we i.e. decided we are forbidden to even think
551 * about such a connection attempt.
552 * XXX: Unify with @local_only handling? --pasky */
553 int silent_fail = 0;
555 csocket->ops->set_state(csocket, state);
557 /* Clear handlers, the connection to the previous RR really timed
558 * out and doesn't interest us anymore. */
559 if (csocket->fd >= 0)
560 close_socket(csocket);
562 for (i = connect_info->triedno + 1; i < connect_info->addrno; i++) {
563 #ifdef CONFIG_IPV6
564 struct sockaddr_in6 addr = *((struct sockaddr_in6 *) &connect_info->addr[i]);
565 int family = addr.sin6_family;
566 #else
567 struct sockaddr_in addr = *((struct sockaddr_in *) &connect_info->addr[i]);
568 int family = addr.sin_family;
569 #endif
570 int pf;
571 int force_family = connect_info->ip_family;
573 connect_info->triedno++;
575 if (only_local) {
576 int local = 0;
577 #ifdef CONFIG_IPV6
578 if (family == AF_INET6)
579 local = check_if_local_address6((struct sockaddr_in6 *) &addr);
580 else
581 #endif
582 local = check_if_local_address4((struct sockaddr_in *) &addr);
584 /* This forbids connections to anything but local, if option is set. */
585 if (!local) {
586 at_least_one_remote_ip = 1;
587 continue;
591 #ifdef CONFIG_IPV6
592 if (family == AF_INET6) {
593 if (!try_ipv6 || (force_family && force_family != 6)) {
594 silent_fail = 1;
595 continue;
597 pf = PF_INET6;
599 } else
600 #endif
601 if (family == AF_INET) {
602 if (!try_ipv4 || (force_family && force_family != 4)) {
603 silent_fail = 1;
604 continue;
606 pf = PF_INET;
608 } else {
609 continue;
611 silent_fail = 0;
613 sock = socket(pf, SOCK_STREAM, IPPROTO_TCP);
614 if (sock == -1) {
615 if (errno && !saved_errno) saved_errno = errno;
616 continue;
619 if (set_nonblocking_fd(sock) < 0) {
620 if (errno && !saved_errno) saved_errno = errno;
621 close(sock);
622 continue;
624 csocket->fd = sock;
626 #ifdef CONFIG_IPV6
627 addr.sin6_port = htons(connect_info->port);
628 #else
629 addr.sin_port = htons(connect_info->port);
630 #endif
632 /* We can set csocket->protocol_family here even if the connection
633 * will fail, as we will use it only when it will be successfully
634 * established. At least I hope that noone else will want to do
635 * something else ;-). --pasky */
636 /* And in fact we must set it early, because of EINPROGRESS. */
638 #ifdef CONFIG_IPV6
639 if (family == AF_INET6) {
640 csocket->protocol_family = EL_PF_INET6;
641 if (connect(sock, (struct sockaddr *) &addr,
642 sizeof(struct sockaddr_in6)) == 0) {
643 /* Success */
644 complete_connect_socket(csocket, NULL, NULL);
645 return;
647 } else
648 #endif
650 csocket->protocol_family = EL_PF_INET;
651 if (connect(sock, (struct sockaddr *) &addr,
652 sizeof(struct sockaddr_in)) == 0) {
653 /* Success */
654 complete_connect_socket(csocket, NULL, NULL);
655 return;
659 if (errno == EALREADY
660 #ifdef EWOULDBLOCK
661 || errno == EWOULDBLOCK
662 #endif
663 || errno == EINPROGRESS) {
664 /* It will take some more time... */
665 set_handlers(sock, NULL, (select_handler_T) connected,
666 (select_handler_T) dns_exception, csocket);
667 csocket->ops->set_state(csocket, connection_state(S_CONN));
668 return;
671 if (errno && !saved_errno) saved_errno = errno;
673 close(sock);
676 assert(i >= connect_info->addrno);
678 /* Tried everything, but it didn't help :(. */
680 if (only_local && !saved_errno && at_least_one_remote_ip) {
681 /* Yes we might hit a local address and fail in the process, but
682 * what matters is the last one because we do not know the
683 * previous one's errno, and the added complexity wouldn't
684 * really be worth it. */
685 csocket->ops->done(csocket, connection_state(S_LOCAL_ONLY));
686 return;
689 /* Retry reporting the errno state only if we already tried something
690 * new. Else use the S_DNS _progress_ state to make sure that no
691 * download callbacks will report any errors. */
692 if (trno != connect_info->triedno && !silent_fail)
693 state = connection_state_for_errno(errno);
694 else if (trno == -1 && silent_fail)
695 /* All failed. */
696 state = connection_state(S_NO_FORCED_DNS);
698 csocket->ops->retry(csocket, state);
702 struct write_buffer {
703 /* A routine called when all the data is sent (therefore this is
704 * _different_ from read_buffer.done !). */
705 socket_write_T done;
707 int length;
708 int pos;
710 unsigned char data[1]; /* must be at end of struct */
713 static int
714 generic_write(struct socket *socket, unsigned char *data, int len)
716 int wr = safe_write(socket->fd, data, len);
718 if (!wr) return SOCKET_CANT_WRITE;
720 if (wr < 0) {
721 #ifdef EWOULDBLOCK
722 if (errno == EWOULDBLOCK) return SOCKET_CANT_WRITE;
723 #endif
724 return SOCKET_SYSCALL_ERROR;
726 return wr;
729 static void
730 write_select(struct socket *socket)
732 struct write_buffer *wb = socket->write_buffer;
733 int wr;
735 assertm(wb != NULL, "write socket has no buffer");
736 if_assert_failed {
737 socket->ops->done(socket, connection_state(S_INTERNAL));
738 return;
741 /* We are making some progress, therefore reset the timeout; ie. when
742 * uploading large files the time needed for all the data to be sent can
743 * easily exceed the timeout. */
744 socket->ops->set_timeout(socket, connection_state(0));
746 #if 0
747 printf("ws: %d\n",wb->length-wb->pos);
748 for (wr = wb->pos; wr < wb->length; wr++) printf("%c", wb->data[wr]);
749 printf("-\n");
750 #endif
752 #ifdef CONFIG_SSL
753 if (socket->ssl) {
754 wr = ssl_write(socket, wb->data + wb->pos, wb->length - wb->pos);
755 } else
756 #endif
758 assert(wb->length - wb->pos > 0);
759 wr = generic_write(socket, wb->data + wb->pos, wb->length - wb->pos);
762 switch (wr) {
763 case SOCKET_CANT_WRITE:
764 socket->ops->retry(socket, connection_state(S_CANT_WRITE));
765 break;
767 case SOCKET_SYSCALL_ERROR:
768 socket->ops->retry(socket, connection_state_for_errno(errno));
769 break;
771 case SOCKET_INTERNAL_ERROR:
772 /* The global errno variable is used for passing
773 * internal connection_state error value. */
774 socket->ops->done(socket, connection_state(errno));
775 break;
777 default:
778 if (wr < 0) break;
780 /*printf("wr: %d\n", wr);*/
781 wb->pos += wr;
783 if (wb->pos == wb->length) {
784 socket_write_T done = wb->done;
786 if (!socket->duplex) {
787 clear_handlers(socket->fd);
789 } else {
790 select_handler_T read_handler;
791 select_handler_T error_handler;
793 read_handler = get_handler(socket->fd, SELECT_HANDLER_READ);
794 error_handler = read_handler
795 ? (select_handler_T) exception
796 : NULL;
798 set_handlers(socket->fd, read_handler, NULL,
799 error_handler, socket);
802 mem_free_set(&socket->write_buffer, NULL);
803 done(socket);
808 void
809 write_to_socket(struct socket *socket, unsigned char *data, int len,
810 struct connection_state state, socket_write_T write_done)
812 select_handler_T read_handler;
813 struct write_buffer *wb;
815 debug_transfer_log(data, len);
817 assert(len > 0);
818 if_assert_failed return;
820 socket->ops->set_timeout(socket, connection_state(0));
822 wb = mem_alloc(sizeof(*wb) + len);
823 if (!wb) {
824 socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
825 return;
828 wb->length = len;
829 wb->pos = 0;
830 wb->done = write_done;
831 memcpy(wb->data, data, len);
832 mem_free_set(&socket->write_buffer, wb);
834 if (socket->duplex) {
835 read_handler = get_handler(socket->fd, SELECT_HANDLER_READ);
836 } else {
837 read_handler = NULL;
840 set_handlers(socket->fd, read_handler, (select_handler_T) write_select,
841 (select_handler_T) exception, socket);
842 socket->ops->set_state(socket, state);
845 #define RD_ALLOC_GR (2<<11) /* 4096 */
846 #define RD_MEM(rb) (sizeof(*(rb)) + 4 * RD_ALLOC_GR + RD_ALLOC_GR)
847 #define RD_SIZE(rb, len) ((RD_MEM(rb) + (len)) & ~(RD_ALLOC_GR - 1))
849 static ssize_t
850 generic_read(struct socket *socket, unsigned char *data, int len)
852 ssize_t rd = safe_read(socket->fd, data, len);
854 if (!rd) return SOCKET_CANT_READ;
856 if (rd < 0) {
857 #ifdef EWOULDBLOCK
858 if (errno == EWOULDBLOCK) return SOCKET_CANT_READ;
859 #endif
860 return SOCKET_SYSCALL_ERROR;
862 return rd;
865 static void
866 read_select(struct socket *socket)
868 struct read_buffer *rb = socket->read_buffer;
869 ssize_t rd;
871 assertm(rb != NULL, "read socket has no buffer");
872 if_assert_failed {
873 socket->ops->done(socket, connection_state(S_INTERNAL));
874 return;
877 /* We are making some progress, therefore reset the timeout; we do this
878 * for read_select() to avoid that the periodic calls to user handlers
879 * has to do it. */
880 socket->ops->set_timeout(socket, connection_state(0));
882 if (!socket->duplex)
883 clear_handlers(socket->fd);
885 if (!rb->freespace) {
886 int size = RD_SIZE(rb, rb->length);
888 rb = mem_realloc(rb, size);
889 if (!rb) {
890 socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
891 return;
893 rb->freespace = size - sizeof(*rb) - rb->length;
894 assert(rb->freespace > 0);
895 socket->read_buffer = rb;
898 #ifdef CONFIG_SSL
899 if (socket->ssl) {
900 rd = ssl_read(socket, rb->data + rb->length, rb->freespace);
901 } else
902 #endif
904 rd = generic_read(socket, rb->data + rb->length, rb->freespace);
907 switch (rd) {
908 #ifdef CONFIG_SSL
909 case SOCKET_SSL_WANT_READ:
910 read_from_socket(socket, rb, connection_state(S_TRANS), rb->done);
911 break;
912 #endif
913 case SOCKET_CANT_READ:
914 if (socket->state != SOCKET_RETRY_ONCLOSE) {
915 socket->state = SOCKET_CLOSED;
916 rb->done(socket, rb);
917 break;
920 socket->ops->retry(socket, connection_state(S_CANT_READ));
921 break;
923 case SOCKET_SYSCALL_ERROR:
924 socket->ops->retry(socket, connection_state_for_errno(errno));
925 break;
927 case SOCKET_INTERNAL_ERROR:
928 /* The global errno variable is used for passing
929 * internal connection_state error value. */
930 socket->ops->done(socket, connection_state(errno));
931 break;
933 default:
934 debug_transfer_log(rb->data + rb->length, rd);
936 rb->length += rd;
937 rb->freespace -= rd;
938 assert(rb->freespace >= 0);
940 rb->done(socket, rb);
944 struct read_buffer *
945 alloc_read_buffer(struct socket *socket)
947 struct read_buffer *rb;
949 rb = mem_calloc(1, RD_SIZE(rb, 0));
950 if (!rb) {
951 socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
952 return NULL;
955 rb->freespace = RD_SIZE(rb, 0) - sizeof(*rb);
957 return rb;
960 #undef RD_ALLOC_GR
961 #undef RD_MEM
962 #undef RD_SIZE
964 void
965 read_from_socket(struct socket *socket, struct read_buffer *buffer,
966 struct connection_state state, socket_read_T done)
968 const int is_buffer_new = (buffer != socket->read_buffer);
969 struct socket_weak_ref ref;
970 select_handler_T write_handler;
972 ref.socket = socket;
973 add_to_list(socket_weak_refs, &ref);
975 buffer->done = done;
977 socket->ops->set_timeout(socket, connection_state(0));
978 socket->ops->set_state(socket, state);
980 del_from_list(&ref);
981 if (ref.socket == NULL) {
982 /* socket->ops->set_state deleted the socket. */
983 if (is_buffer_new)
984 mem_free(buffer);
985 return;
988 if (socket->read_buffer && buffer != socket->read_buffer)
989 mem_free(socket->read_buffer);
990 socket->read_buffer = buffer;
992 if (socket->duplex) {
993 write_handler = get_handler(socket->fd, SELECT_HANDLER_WRITE);
994 } else {
995 write_handler = NULL;
998 set_handlers(socket->fd, (select_handler_T) read_select, write_handler,
999 (select_handler_T) exception, socket);
1002 static void
1003 read_response_from_socket(struct socket *socket)
1005 struct read_buffer *rb = alloc_read_buffer(socket);
1007 if (rb) read_from_socket(socket, rb, connection_state(S_SENT),
1008 socket->read_done);
1011 void
1012 request_from_socket(struct socket *socket, unsigned char *data, int datalen,
1013 struct connection_state state, enum socket_state sock_state,
1014 socket_read_T read_done)
1016 socket->read_done = read_done;
1017 socket->state = sock_state;
1018 write_to_socket(socket, data, datalen, state,
1019 read_response_from_socket);
1022 void
1023 kill_buffer_data(struct read_buffer *rb, int n)
1025 assertm(n >= 0 && n <= rb->length, "bad number of bytes: %d", n);
1026 if_assert_failed { rb->length = 0; return; }
1028 if (!n) return; /* FIXME: We accept to kill 0 bytes... */
1029 rb->length -= n;
1030 memmove(rb->data, rb->data + n, rb->length);
1031 rb->freespace += n;