Bug 1013: Don't assume errno is between 0 and 100000
[elinks.git] / src / network / socket.c
blob4179b152690c62b051b7fbe1af4c7122fccda46b
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. */
73 /* To enable logging of tranfers, for debugging purposes. */
74 #if 0
76 #define DEBUG_TRANSFER_LOGFILE "/tmp/log"
78 static void
79 debug_transfer_log(unsigned char *data, int len)
81 int fd = open(DEBUG_TRANSFER_LOGFILE, O_WRONLY | O_APPEND | O_CREAT, 0622);
83 if (fd == -1) return;
85 set_bin(fd);
86 write(fd, data, len < 0 ? strlen(data) : len);
87 close(fd);
89 #undef DEBUG_TRANSFER_LOGFILE
91 #else
92 #define debug_transfer_log(data, len)
93 #endif
96 static struct connect_info *
97 init_connection_info(struct uri *uri, struct socket *socket,
98 socket_connect_T connect_done)
100 struct connect_info *connect_info = mem_calloc(1, sizeof(*connect_info));
102 if (!connect_info) return NULL;
104 connect_info->done = connect_done;
105 connect_info->port = get_uri_port(uri);
106 connect_info->ip_family = uri->ip_family;
107 connect_info->triedno = -1;
108 connect_info->addr = NULL;
109 connect_info->uri = get_uri_reference(uri);
111 return connect_info;
114 static void
115 done_connection_info(struct socket *socket)
117 struct connect_info *connect_info = socket->connect_info;
119 assert(socket->connect_info);
121 if (connect_info->dnsquery) kill_dns_request(&connect_info->dnsquery);
123 mem_free_if(connect_info->addr);
124 done_uri(connect_info->uri);
125 mem_free_set(&socket->connect_info, NULL);
128 struct socket *
129 init_socket(void *conn, struct socket_operations *ops)
131 struct socket *socket;
133 socket = mem_calloc(1, sizeof(*socket));
134 if (!socket) return NULL;
136 socket->fd = -1;
137 socket->conn = conn;
138 socket->ops = ops;
140 return socket;
143 void
144 done_socket(struct socket *socket)
146 close_socket(socket);
148 if (socket->connect_info)
149 done_connection_info(socket);
151 mem_free_set(&socket->read_buffer, NULL);
152 mem_free_set(&socket->write_buffer, NULL);
155 void
156 close_socket(struct socket *socket)
158 if (socket->fd == -1) return;
159 #ifdef CONFIG_SSL
160 if (socket->ssl) ssl_close(socket);
161 #endif
162 close(socket->fd);
163 clear_handlers(socket->fd);
164 socket->fd = -1;
167 void
168 dns_exception(struct socket *socket)
170 connect_socket(socket, connection_state(S_EXCEPT));
173 static void
174 exception(struct socket *socket)
176 socket->ops->retry(socket, connection_state(S_EXCEPT));
180 void
181 timeout_socket(struct socket *socket)
183 if (!socket->connect_info) {
184 socket->ops->retry(socket, connection_state(S_TIMEOUT));
185 return;
188 /* Is the DNS resolving still in progress? */
189 if (socket->connect_info->dnsquery) {
190 socket->ops->done(socket, connection_state(S_TIMEOUT));
191 return;
194 /* Try the next address, */
195 connect_socket(socket, connection_state(S_TIMEOUT));
197 /* Reset the timeout if connect_socket() started a new attempt
198 * to connect. */
199 if (socket->connect_info)
200 socket->ops->set_timeout(socket, connection_state(0));
204 /* DNS callback. */
205 static void
206 dns_found(struct socket *socket, struct sockaddr_storage *addr, int addrlen)
208 struct connect_info *connect_info = socket->connect_info;
209 int size;
211 if (!addr) {
212 socket->ops->done(socket, connection_state(S_NO_DNS));
213 return;
216 assert(connect_info);
218 size = sizeof(*addr) * addrlen;
220 connect_info->addr = mem_alloc(size);
221 if (!connect_info->addr) {
222 socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
223 return;
226 memcpy(connect_info->addr, addr, size);
227 connect_info->addrno = addrlen;
229 /* XXX: Passing non-result state here is bad but a lack of alternatives
230 * makes it so. Well adding get_state() socket operation could maybe fix
231 * it but the returned state would most likely be a non-result one at
232 * this point in the connection lifecycle. This will, however, only be a
233 * problem if connect_socket() fails without doing any system calls
234 * which is only the case when forcing the IP family. So it is better to
235 * handle it in connect_socket(). */
236 connect_socket(socket, connection_state(S_CONN));
239 void
240 make_connection(struct socket *socket, struct uri *uri,
241 socket_connect_T connect_done, int no_cache)
243 unsigned char *host = get_uri_string(uri, URI_DNS_HOST);
244 struct connect_info *connect_info;
245 enum dns_result result;
247 socket->ops->set_timeout(socket, connection_state(0));
249 if (!host) {
250 socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
251 return;
254 connect_info = init_connection_info(uri, socket, connect_done);
255 if (!connect_info) {
256 mem_free(host);
257 socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
258 return;
261 socket->connect_info = connect_info;
262 /* XXX: Keep here and not in init_connection_info() to make
263 * complete_connect_socket() work from the HTTP implementation. */
264 socket->need_ssl = get_protocol_need_ssl(uri->protocol);
265 if (!socket->set_no_tls) {
266 enum blacklist_flags flags = get_blacklist_flags(uri);
267 socket->no_tls = ((flags & SERVER_BLACKLIST_NO_TLS) != 0);
268 socket->set_no_tls = 1;
271 debug_transfer_log("\nCONNECTION: ", -1);
272 debug_transfer_log(host, -1);
273 debug_transfer_log("\n", -1);
275 result = find_host(host, &connect_info->dnsquery, (dns_callback_T) dns_found,
276 socket, no_cache);
278 mem_free(host);
280 if (result == DNS_ASYNC)
281 socket->ops->set_state(socket, connection_state(S_DNS));
285 /* Returns negative if error, otherwise pasv socket's fd. */
287 get_pasv_socket(struct socket *ctrl_socket, struct sockaddr_storage *addr)
289 struct sockaddr_in bind_addr4;
290 struct sockaddr *bind_addr;
291 struct sockaddr *pasv_addr = (struct sockaddr *) addr;
292 size_t addrlen;
293 int sock = -1;
294 int syspf; /* Protocol Family given to system, not EL_PF_... */
295 socklen_t len;
296 #ifdef CONFIG_IPV6
297 struct sockaddr_in6 bind_addr6;
299 if (ctrl_socket->protocol_family == EL_PF_INET6) {
300 bind_addr = (struct sockaddr *) &bind_addr6;
301 addrlen = sizeof(bind_addr6);
302 syspf = PF_INET6;
303 } else
304 #endif
306 bind_addr = (struct sockaddr *) &bind_addr4;
307 addrlen = sizeof(bind_addr4);
308 syspf = PF_INET;
311 memset(pasv_addr, 0, addrlen);
312 memset(bind_addr, 0, addrlen);
314 /* Get our endpoint of the control socket */
315 len = addrlen;
316 if (getsockname(ctrl_socket->fd, pasv_addr, &len)) {
317 sock_error:
318 if (sock != -1) close(sock);
319 ctrl_socket->ops->retry(ctrl_socket,
320 connection_state_for_errno(errno));
321 return -1;
324 /* Get a passive socket */
326 sock = socket(syspf, SOCK_STREAM, IPPROTO_TCP);
327 if (sock < 0)
328 goto sock_error;
330 /* Set it non-blocking */
332 if (set_nonblocking_fd(sock) < 0)
333 goto sock_error;
335 /* Bind it to some port */
337 memcpy(bind_addr, pasv_addr, addrlen);
338 #ifdef CONFIG_IPV6
339 if (ctrl_socket->protocol_family == EL_PF_INET6)
340 bind_addr6.sin6_port = 0;
341 else
342 #endif
343 bind_addr4.sin_port = 0;
345 if (bind(sock, bind_addr, addrlen))
346 goto sock_error;
348 /* Get our endpoint of the passive socket and save it to port */
350 len = addrlen;
351 if (getsockname(sock, pasv_addr, &len))
352 goto sock_error;
354 /* Go listen */
356 if (listen(sock, 1))
357 goto sock_error;
359 set_ip_tos_throughput(sock);
361 return sock;
364 #ifdef CONFIG_IPV6
365 static inline int
366 check_if_local_address6(struct sockaddr_in6 *addr)
368 struct ifaddrs *ifaddrs;
369 int local = IN6_IS_ADDR_LOOPBACK(&(addr->sin6_addr));
371 if (!local && !getifaddrs(&ifaddrs)) {
372 struct ifaddrs *ifa;
374 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
375 if (!ifa->ifa_addr)
376 continue;
378 if (ifa->ifa_addr->sa_family == AF_INET6
379 && !memcmp(&addr->sin6_addr.s6_addr,
380 &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr.s6_addr,
381 sizeof(addr->sin6_addr.s6_addr))) {
382 local = 1;
383 break;
386 if (ifa->ifa_addr->sa_family == AF_INET
387 && !memcmp(&((struct sockaddr_in *) &addr)->sin_addr.s_addr,
388 &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr,
389 sizeof(((struct sockaddr_in *) &addr)->sin_addr.s_addr))) {
390 local = 1;
391 break;
395 freeifaddrs(ifaddrs);
398 return local;
400 #endif /* CONFIG_IPV6 */
402 static inline int
403 check_if_local_address4(struct sockaddr_in *addr)
405 struct ifaddrs *ifaddrs;
406 int local = (ntohl(addr->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
408 if (!local && !getifaddrs(&ifaddrs)) {
409 struct ifaddrs *ifa;
411 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
412 if (!ifa->ifa_addr)
413 continue;
415 if (ifa->ifa_addr->sa_family != AF_INET) continue;
417 if (!memcmp(&addr->sin_addr.s_addr,
418 &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr,
419 sizeof(addr->sin_addr.s_addr))) {
420 local = 1;
421 break;
425 freeifaddrs(ifaddrs);
428 return local;
432 void
433 complete_connect_socket(struct socket *socket, struct uri *uri,
434 socket_connect_T done)
436 struct connect_info *connect_info = socket->connect_info;
438 if (connect_info && connect_info->uri) {
439 /* Remember whether the server supported TLS or not.
440 * Then the next request can immediately use the right
441 * protocol. This is important for HTTP POST requests
442 * because it is not safe to silently retry them. The
443 * uri parameter is normally NULL here so don't use it. */
444 if (socket->no_tls)
445 add_blacklist_entry(connect_info->uri,
446 SERVER_BLACKLIST_NO_TLS);
447 else
448 del_blacklist_entry(connect_info->uri,
449 SERVER_BLACKLIST_NO_TLS);
452 /* This is a special case used by the HTTP implementation to acquire an
453 * SSL link for handling CONNECT requests. */
454 if (!connect_info) {
455 assert(uri && socket);
456 connect_info = init_connection_info(uri, socket, done);
457 if (!connect_info) {
458 socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
459 return;
462 socket->connect_info = connect_info;
465 #ifdef CONFIG_SSL
466 /* Check if the connection should run over an encrypted link */
467 if (socket->need_ssl
468 && !socket->ssl
469 && ssl_connect(socket) < 0)
470 return;
471 #endif
473 if (connect_info->done)
474 connect_info->done(socket);
476 done_connection_info(socket);
479 /* Select handler which is set for the socket descriptor when connect() has
480 * indicated (via errno) that it is in progress. On completion this handler gets
481 * called. */
482 static void
483 connected(struct socket *socket)
485 int err = 0;
486 struct connection_state state = connection_state(0);
487 socklen_t len = sizeof(err);
489 assertm(socket->connect_info != NULL, "Lost connect_info!");
490 if_assert_failed return;
492 if (getsockopt(socket->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) == 0) {
493 /* Why does EMX return so large values? */
494 if (err >= 10000) err -= 10000;
495 if (err != 0)
496 state = connection_state_for_errno(err);
497 else
498 state = connection_state(0);
499 } else {
500 /* getsockopt() failed */
501 if (errno != 0)
502 state = connection_state_for_errno(errno);
503 else
504 state = connection_state(S_STATE);
507 if (!is_in_state(state, 0)) {
508 /* There are maybe still some more candidates. */
509 connect_socket(socket, state);
510 return;
513 complete_connect_socket(socket, NULL, NULL);
516 void
517 connect_socket(struct socket *csocket, struct connection_state state)
519 int sock = -1;
520 struct connect_info *connect_info = csocket->connect_info;
521 int i;
522 int trno = connect_info->triedno;
523 int only_local = get_cmd_opt_bool("localhost");
524 int saved_errno = 0;
525 int at_least_one_remote_ip = 0;
526 #ifdef CONFIG_IPV6
527 int try_ipv6 = get_opt_bool("connection.try_ipv6");
528 #endif
529 int try_ipv4 = get_opt_bool("connection.try_ipv4");
530 /* We tried something but we failed in such a way that we would rather
531 * prefer the connection to retain the information about previous
532 * failures. That is, we i.e. decided we are forbidden to even think
533 * about such a connection attempt.
534 * XXX: Unify with @local_only handling? --pasky */
535 int silent_fail = 0;
537 csocket->ops->set_state(csocket, state);
539 /* Clear handlers, the connection to the previous RR really timed
540 * out and doesn't interest us anymore. */
541 if (csocket->fd >= 0)
542 close_socket(csocket);
544 for (i = connect_info->triedno + 1; i < connect_info->addrno; i++) {
545 #ifdef CONFIG_IPV6
546 struct sockaddr_in6 addr = *((struct sockaddr_in6 *) &connect_info->addr[i]);
547 int family = addr.sin6_family;
548 #else
549 struct sockaddr_in addr = *((struct sockaddr_in *) &connect_info->addr[i]);
550 int family = addr.sin_family;
551 #endif
552 int pf;
553 int force_family = connect_info->ip_family;
555 connect_info->triedno++;
557 if (only_local) {
558 int local = 0;
559 #ifdef CONFIG_IPV6
560 if (family == AF_INET6)
561 local = check_if_local_address6((struct sockaddr_in6 *) &addr);
562 else
563 #endif
564 local = check_if_local_address4((struct sockaddr_in *) &addr);
566 /* This forbids connections to anything but local, if option is set. */
567 if (!local) {
568 at_least_one_remote_ip = 1;
569 continue;
573 #ifdef CONFIG_IPV6
574 if (family == AF_INET6) {
575 if (!try_ipv6 || (force_family && force_family != 6)) {
576 silent_fail = 1;
577 continue;
579 pf = PF_INET6;
581 } else
582 #endif
583 if (family == AF_INET) {
584 if (!try_ipv4 || (force_family && force_family != 4)) {
585 silent_fail = 1;
586 continue;
588 pf = PF_INET;
590 } else {
591 continue;
593 silent_fail = 0;
595 sock = socket(pf, SOCK_STREAM, IPPROTO_TCP);
596 if (sock == -1) {
597 if (errno && !saved_errno) saved_errno = errno;
598 continue;
601 if (set_nonblocking_fd(sock) < 0) {
602 if (errno && !saved_errno) saved_errno = errno;
603 close(sock);
604 continue;
606 csocket->fd = sock;
608 #ifdef CONFIG_IPV6
609 addr.sin6_port = htons(connect_info->port);
610 #else
611 addr.sin_port = htons(connect_info->port);
612 #endif
614 /* We can set csocket->protocol_family here even if the connection
615 * will fail, as we will use it only when it will be successfully
616 * established. At least I hope that noone else will want to do
617 * something else ;-). --pasky */
618 /* And in fact we must set it early, because of EINPROGRESS. */
620 #ifdef CONFIG_IPV6
621 if (family == AF_INET6) {
622 csocket->protocol_family = EL_PF_INET6;
623 if (connect(sock, (struct sockaddr *) &addr,
624 sizeof(struct sockaddr_in6)) == 0) {
625 /* Success */
626 complete_connect_socket(csocket, NULL, NULL);
627 return;
629 } else
630 #endif
632 csocket->protocol_family = EL_PF_INET;
633 if (connect(sock, (struct sockaddr *) &addr,
634 sizeof(struct sockaddr_in)) == 0) {
635 /* Success */
636 complete_connect_socket(csocket, NULL, NULL);
637 return;
641 if (errno == EALREADY
642 #ifdef EWOULDBLOCK
643 || errno == EWOULDBLOCK
644 #endif
645 || errno == EINPROGRESS) {
646 /* It will take some more time... */
647 set_handlers(sock, NULL, (select_handler_T) connected,
648 (select_handler_T) dns_exception, csocket);
649 csocket->ops->set_state(csocket, connection_state(S_CONN));
650 return;
653 if (errno && !saved_errno) saved_errno = errno;
655 close(sock);
658 assert(i >= connect_info->addrno);
660 /* Tried everything, but it didn't help :(. */
662 if (only_local && !saved_errno && at_least_one_remote_ip) {
663 /* Yes we might hit a local address and fail in the process, but
664 * what matters is the last one because we do not know the
665 * previous one's errno, and the added complexity wouldn't
666 * really be worth it. */
667 csocket->ops->done(csocket, connection_state(S_LOCAL_ONLY));
668 return;
671 /* Retry reporting the errno state only if we already tried something
672 * new. Else use the S_DNS _progress_ state to make sure that no
673 * download callbacks will report any errors. */
674 if (trno != connect_info->triedno && !silent_fail)
675 state = connection_state_for_errno(errno);
676 else if (trno == -1 && silent_fail)
677 /* All failed. */
678 state = connection_state(S_NO_FORCED_DNS);
680 csocket->ops->retry(csocket, state);
684 struct write_buffer {
685 /* A routine called when all the data is sent (therefore this is
686 * _different_ from read_buffer.done !). */
687 socket_write_T done;
689 int length;
690 int pos;
692 unsigned char data[1]; /* must be at end of struct */
695 static int
696 generic_write(struct socket *socket, unsigned char *data, int len)
698 int wr = safe_write(socket->fd, data, len);
700 if (!wr) return SOCKET_CANT_WRITE;
702 return wr < 0 ? SOCKET_SYSCALL_ERROR : wr;
705 static void
706 write_select(struct socket *socket)
708 struct write_buffer *wb = socket->write_buffer;
709 int wr;
711 assertm(wb != NULL, "write socket has no buffer");
712 if_assert_failed {
713 socket->ops->done(socket, connection_state(S_INTERNAL));
714 return;
717 /* We are making some progress, therefore reset the timeout; ie. when
718 * uploading large files the time needed for all the data to be sent can
719 * easily exceed the timeout. */
720 socket->ops->set_timeout(socket, connection_state(0));
722 #if 0
723 printf("ws: %d\n",wb->length-wb->pos);
724 for (wr = wb->pos; wr < wb->length; wr++) printf("%c", wb->data[wr]);
725 printf("-\n");
726 #endif
728 #ifdef CONFIG_SSL
729 if (socket->ssl) {
730 wr = ssl_write(socket, wb->data + wb->pos, wb->length - wb->pos);
731 } else
732 #endif
734 assert(wb->length - wb->pos > 0);
735 wr = generic_write(socket, wb->data + wb->pos, wb->length - wb->pos);
738 switch (wr) {
739 case SOCKET_CANT_WRITE:
740 socket->ops->retry(socket, connection_state(S_CANT_WRITE));
741 break;
743 case SOCKET_SYSCALL_ERROR:
744 socket->ops->retry(socket, connection_state_for_errno(errno));
745 break;
747 case SOCKET_INTERNAL_ERROR:
748 /* The global errno variable is used for passing
749 * internal connection_state error value. */
750 socket->ops->done(socket, connection_state(errno));
751 break;
753 default:
754 if (wr < 0) break;
756 /*printf("wr: %d\n", wr);*/
757 wb->pos += wr;
759 if (wb->pos == wb->length) {
760 socket_write_T done = wb->done;
762 if (!socket->duplex) {
763 clear_handlers(socket->fd);
765 } else {
766 select_handler_T read_handler;
767 select_handler_T error_handler;
769 read_handler = get_handler(socket->fd, SELECT_HANDLER_READ);
770 error_handler = read_handler
771 ? (select_handler_T) exception
772 : NULL;
774 set_handlers(socket->fd, read_handler, NULL,
775 error_handler, socket);
778 mem_free_set(&socket->write_buffer, NULL);
779 done(socket);
784 void
785 write_to_socket(struct socket *socket, unsigned char *data, int len,
786 struct connection_state state, socket_write_T write_done)
788 select_handler_T read_handler;
789 struct write_buffer *wb;
791 debug_transfer_log(data, len);
793 assert(len > 0);
794 if_assert_failed return;
796 socket->ops->set_timeout(socket, connection_state(0));
798 wb = mem_alloc(sizeof(*wb) + len);
799 if (!wb) {
800 socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
801 return;
804 wb->length = len;
805 wb->pos = 0;
806 wb->done = write_done;
807 memcpy(wb->data, data, len);
808 mem_free_set(&socket->write_buffer, wb);
810 if (socket->duplex) {
811 read_handler = get_handler(socket->fd, SELECT_HANDLER_READ);
812 } else {
813 read_handler = NULL;
816 set_handlers(socket->fd, read_handler, (select_handler_T) write_select,
817 (select_handler_T) exception, socket);
818 socket->ops->set_state(socket, state);
821 #define RD_ALLOC_GR (2<<11) /* 4096 */
822 #define RD_MEM(rb) (sizeof(*(rb)) + 4 * RD_ALLOC_GR + RD_ALLOC_GR)
823 #define RD_SIZE(rb, len) ((RD_MEM(rb) + (len)) & ~(RD_ALLOC_GR - 1))
825 static ssize_t
826 generic_read(struct socket *socket, unsigned char *data, int len)
828 ssize_t rd = safe_read(socket->fd, data, len);
830 if (!rd) return SOCKET_CANT_READ;
832 return rd < 0 ? SOCKET_SYSCALL_ERROR : rd;
835 static void
836 read_select(struct socket *socket)
838 struct read_buffer *rb = socket->read_buffer;
839 ssize_t rd;
841 assertm(rb != NULL, "read socket has no buffer");
842 if_assert_failed {
843 socket->ops->done(socket, connection_state(S_INTERNAL));
844 return;
847 /* We are making some progress, therefore reset the timeout; we do this
848 * for read_select() to avoid that the periodic calls to user handlers
849 * has to do it. */
850 socket->ops->set_timeout(socket, connection_state(0));
852 if (!socket->duplex)
853 clear_handlers(socket->fd);
855 if (!rb->freespace) {
856 int size = RD_SIZE(rb, rb->length);
858 rb = mem_realloc(rb, size);
859 if (!rb) {
860 socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
861 return;
863 rb->freespace = size - sizeof(*rb) - rb->length;
864 assert(rb->freespace > 0);
865 socket->read_buffer = rb;
868 #ifdef CONFIG_SSL
869 if (socket->ssl) {
870 rd = ssl_read(socket, rb->data + rb->length, rb->freespace);
871 } else
872 #endif
874 rd = generic_read(socket, rb->data + rb->length, rb->freespace);
877 switch (rd) {
878 #ifdef CONFIG_SSL
879 case SOCKET_SSL_WANT_READ:
880 read_from_socket(socket, rb, connection_state(S_TRANS), rb->done);
881 break;
882 #endif
883 case SOCKET_CANT_READ:
884 if (socket->state != SOCKET_RETRY_ONCLOSE) {
885 socket->state = SOCKET_CLOSED;
886 rb->done(socket, rb);
887 break;
890 socket->ops->retry(socket, connection_state(S_CANT_READ));
891 break;
893 case SOCKET_SYSCALL_ERROR:
894 socket->ops->retry(socket, connection_state_for_errno(errno));
895 break;
897 case SOCKET_INTERNAL_ERROR:
898 /* The global errno variable is used for passing
899 * internal connection_state error value. */
900 socket->ops->done(socket, connection_state(errno));
901 break;
903 default:
904 debug_transfer_log(rb->data + rb->length, rd);
906 rb->length += rd;
907 rb->freespace -= rd;
908 assert(rb->freespace >= 0);
910 rb->done(socket, rb);
914 struct read_buffer *
915 alloc_read_buffer(struct socket *socket)
917 struct read_buffer *rb;
919 rb = mem_calloc(1, RD_SIZE(rb, 0));
920 if (!rb) {
921 socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
922 return NULL;
925 rb->freespace = RD_SIZE(rb, 0) - sizeof(*rb);
927 return rb;
930 #undef RD_ALLOC_GR
931 #undef RD_MEM
932 #undef RD_SIZE
934 void
935 read_from_socket(struct socket *socket, struct read_buffer *buffer,
936 struct connection_state state, socket_read_T done)
938 select_handler_T write_handler;
940 buffer->done = done;
942 socket->ops->set_timeout(socket, connection_state(0));
943 socket->ops->set_state(socket, state);
945 if (socket->read_buffer && buffer != socket->read_buffer)
946 mem_free(socket->read_buffer);
947 socket->read_buffer = buffer;
949 if (socket->duplex) {
950 write_handler = get_handler(socket->fd, SELECT_HANDLER_WRITE);
951 } else {
952 write_handler = NULL;
955 set_handlers(socket->fd, (select_handler_T) read_select, write_handler,
956 (select_handler_T) exception, socket);
959 static void
960 read_response_from_socket(struct socket *socket)
962 struct read_buffer *rb = alloc_read_buffer(socket);
964 if (rb) read_from_socket(socket, rb, connection_state(S_SENT),
965 socket->read_done);
968 void
969 request_from_socket(struct socket *socket, unsigned char *data, int datalen,
970 struct connection_state state, enum socket_state sock_state,
971 socket_read_T read_done)
973 socket->read_done = read_done;
974 socket->state = sock_state;
975 write_to_socket(socket, data, datalen, state,
976 read_response_from_socket);
979 void
980 kill_buffer_data(struct read_buffer *rb, int n)
982 assertm(n >= 0 && n <= rb->length, "bad number of bytes: %d", n);
983 if_assert_failed { rb->length = 0; return; }
985 if (!n) return; /* FIXME: We accept to kill 0 bytes... */
986 rb->length -= n;
987 memmove(rb->data, rb->data + n, rb->length);
988 rb->freespace += n;