Initial commit of the HEAD branch of the ELinks CVS repository, as of
[elinks/images.git] / src / network / socket.c
blobb3a3d4c9db7bfffcc0c8ae6fdde31b080b6053b9
1 /* Sockets-o-matic */
2 /* $Id: socket.c,v 1.245 2005/06/24 12:15:56 jonas Exp $ */
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
8 #include <errno.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #ifdef HAVE_NETINET_IN_H
12 #include <netinet/in.h> /* OS/2 needs this after sys/types.h */
13 #endif
14 #ifdef HAVE_SYS_SOCKET_H
15 #include <sys/socket.h> /* OS/2 needs this after sys/types.h */
16 #endif
17 #ifdef HAVE_FCNTL_H
18 #include <fcntl.h> /* OS/2 needs this after sys/types.h */
19 #endif
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
24 #ifdef HAVE_GETIFADDRS
25 #ifdef HAVE_NETDB_H
26 #include <netdb.h>
27 #endif
28 #ifdef HAVE_NET_IF_H
29 #include <net/if.h>
30 #endif
31 #ifdef HAVE_IFADDRS_H
32 #include <ifaddrs.h> /* getifaddrs() */
33 #endif
34 #endif /* HAVE_GETIFADDRS */
36 #include "elinks.h"
38 #include "config/options.h"
39 #include "main/select.h"
40 #include "network/connection.h"
41 #include "network/dns.h"
42 #include "network/socket.h"
43 #include "network/ssl/socket.h"
44 #include "osdep/osdep.h"
45 #include "osdep/getifaddrs.h"
46 #include "protocol/protocol.h"
47 #include "protocol/uri.h"
48 #include "util/error.h"
49 #include "util/memory.h"
50 #include "util/string.h"
53 /* Holds information used during the connection establishing phase. */
54 struct connect_info {
55 struct sockaddr_storage *addr; /* Array of found addresses. */
56 int addrno; /* Number of found addresses. */
57 int triedno; /* Index of last tried address */
58 socket_connect_T done; /* Callback signaled when connected. */
59 void *dnsquery; /* Pointer to DNS query info. */
60 int port; /* Which port to bind to. */
61 int ip_family; /* If non-zero, force to IP version. */
65 /* To enable logging of tranfers, for debugging purposes. */
66 #if 0
68 #define DEBUG_TRANSFER_LOGFILE "/tmp/log"
70 static void
71 debug_transfer_log(unsigned char *data, int len)
73 int fd = open(DEBUG_TRANSFER_LOGFILE, O_WRONLY | O_APPEND | O_CREAT, 0622);
75 if (fd == -1) return;
77 set_bin(fd);
78 write(fd, data, len < 0 ? strlen(data) : len);
79 close(fd);
81 #undef DEBUG_TRANSFER_LOGFILE
83 #else
84 #define debug_transfer_log(data, len)
85 #endif
88 static struct connect_info *
89 init_connection_info(struct uri *uri, struct socket *socket,
90 socket_connect_T connect_done)
92 struct connect_info *connect_info = mem_calloc(1, sizeof(*connect_info));
94 if (!connect_info) return NULL;
96 connect_info->done = connect_done;
97 connect_info->port = get_uri_port(uri);
98 connect_info->ip_family = uri->ip_family;
99 connect_info->triedno = -1;
100 connect_info->addr = NULL;
102 return connect_info;
105 static void
106 done_connection_info(struct socket *socket)
108 struct connect_info *connect_info = socket->connect_info;
110 assert(socket->connect_info);
112 if (connect_info->dnsquery) kill_dns_request(&connect_info->dnsquery);
114 mem_free_if(connect_info->addr);
115 mem_free_set(&socket->connect_info, NULL);
118 struct socket *
119 init_socket(void *conn, struct socket_operations *ops)
121 struct socket *socket;
123 socket = mem_calloc(1, sizeof(*socket));
124 if (!socket) return NULL;
126 socket->fd = -1;
127 socket->conn = conn;
128 socket->ops = ops;
130 return socket;
133 void
134 done_socket(struct socket *socket)
136 close_socket(socket);
138 if (socket->connect_info)
139 done_connection_info(socket);
141 mem_free_set(&socket->read_buffer, NULL);
142 mem_free_set(&socket->write_buffer, NULL);
145 void
146 close_socket(struct socket *socket)
148 if (socket->fd == -1) return;
149 #ifdef CONFIG_SSL
150 if (socket->ssl) ssl_close(socket);
151 #endif
152 close(socket->fd);
153 clear_handlers(socket->fd);
154 socket->fd = -1;
157 void
158 dns_exception(struct socket *socket)
160 connect_socket(socket, S_EXCEPT);
163 static void
164 exception(struct socket *socket)
166 socket->ops->retry(socket, S_EXCEPT);
170 void
171 timeout_socket(struct socket *socket)
173 if (!socket->connect_info) {
174 socket->ops->retry(socket, S_TIMEOUT);
175 return;
178 /* Is the DNS resolving still in progress? */
179 if (socket->connect_info->dnsquery) {
180 socket->ops->done(socket, S_TIMEOUT);
181 return;
184 /* Try the next address, */
185 connect_socket(socket, S_TIMEOUT);
187 /* Reset the timeout if connect_socket() started a new attempt
188 * to connect. */
189 if (socket->connect_info)
190 socket->ops->set_timeout(socket, 0);
194 /* DNS callback. */
195 static void
196 dns_found(struct socket *socket, struct sockaddr_storage *addr, int addrlen)
198 struct connect_info *connect_info = socket->connect_info;
199 int size;
201 if (!addr) {
202 socket->ops->done(socket, S_NO_DNS);
203 return;
206 assert(connect_info);
208 size = sizeof(*addr) * addrlen;
210 connect_info->addr = mem_alloc(size);
211 if (!connect_info->addr) {
212 socket->ops->done(socket, S_OUT_OF_MEM);
213 return;
216 memcpy(connect_info->addr, addr, size);
217 connect_info->addrno = addrlen;
219 /* XXX: Passing non-result state here is bad but a lack of alternatives
220 * makes it so. Well adding get_state() socket operation could maybe fix
221 * it but the returned state would most likely be a non-result one at
222 * this point in the connection lifecycle. This will, however, only be a
223 * problem if connect_socket() fails without doing any system calls
224 * which is only the case when forcing the IP family. So it is better to
225 * handle it in connect_socket(). */
226 connect_socket(socket, S_CONN);
229 void
230 make_connection(struct socket *socket, struct uri *uri,
231 socket_connect_T connect_done, int no_cache)
233 unsigned char *host = get_uri_string(uri, URI_DNS_HOST);
234 struct connect_info *connect_info;
235 enum dns_result result;
237 socket->ops->set_timeout(socket, 0);
239 if (!host) {
240 socket->ops->retry(socket, S_OUT_OF_MEM);
241 return;
244 connect_info = init_connection_info(uri, socket, connect_done);
245 if (!connect_info) {
246 mem_free(host);
247 socket->ops->retry(socket, S_OUT_OF_MEM);
248 return;
251 socket->connect_info = connect_info;
252 /* XXX: Keep here and not in init_connection_info() to make
253 * complete_connect_socket() work from the HTTP implementation. */
254 socket->need_ssl = get_protocol_need_ssl(uri->protocol);
256 debug_transfer_log("\nCONNECTION: ", -1);
257 debug_transfer_log(host, -1);
258 debug_transfer_log("\n", -1);
260 result = find_host(host, &connect_info->dnsquery, (dns_callback_T) dns_found,
261 socket, no_cache);
263 mem_free(host);
265 if (result == DNS_ASYNC)
266 socket->ops->set_state(socket, S_DNS);
270 /* Returns negative if error, otherwise pasv socket's fd. */
272 get_pasv_socket(struct socket *ctrl_socket, struct sockaddr_storage *addr)
274 struct sockaddr_in bind_addr4;
275 struct sockaddr *bind_addr;
276 struct sockaddr *pasv_addr = (struct sockaddr *) addr;
277 size_t addrlen;
278 int sock = -1;
279 int len;
280 #ifdef CONFIG_IPV6
281 struct sockaddr_in6 bind_addr6;
283 if (ctrl_socket->protocol_family == 1) {
284 bind_addr = (struct sockaddr *) &bind_addr6;
285 addrlen = sizeof(bind_addr6);
286 } else
287 #endif
289 bind_addr = (struct sockaddr *) &bind_addr4;
290 addrlen = sizeof(bind_addr4);
293 memset(pasv_addr, 0, sizeof(addrlen));
294 memset(bind_addr, 0, sizeof(addrlen));
296 /* Get our endpoint of the control socket */
297 len = addrlen;
298 if (getsockname(ctrl_socket->fd, pasv_addr, &len)) {
299 sock_error:
300 if (sock != -1) close(sock);
301 ctrl_socket->ops->retry(ctrl_socket, -errno);
302 return -1;
305 /* Get a passive socket */
307 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
308 if (sock < 0)
309 goto sock_error;
311 /* Set it non-blocking */
313 if (set_nonblocking_fd(sock) < 0)
314 goto sock_error;
316 /* Bind it to some port */
318 memcpy(bind_addr, pasv_addr, addrlen);
319 #ifdef CONFIG_IPV6
320 if (ctrl_socket->protocol_family == 1)
321 bind_addr6.sin6_port = 0;
322 else
323 #endif
324 bind_addr4.sin_port = 0;
326 if (bind(sock, bind_addr, addrlen))
327 goto sock_error;
329 /* Get our endpoint of the passive socket and save it to port */
331 len = addrlen;
332 if (getsockname(sock, pasv_addr, &len))
333 goto sock_error;
335 /* Go listen */
337 if (listen(sock, 1))
338 goto sock_error;
340 set_ip_tos_throughput(sock);
342 return sock;
345 #ifdef CONFIG_IPV6
346 static inline int
347 check_if_local_address6(struct sockaddr_in6 *addr)
349 struct ifaddrs *ifaddrs;
350 int local = IN6_IS_ADDR_LOOPBACK(&(addr->sin6_addr));
352 if (!local && !getifaddrs(&ifaddrs)) {
353 struct ifaddrs *ifa;
355 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
356 if (!ifa->ifa_addr)
357 continue;
359 if (ifa->ifa_addr->sa_family == AF_INET6
360 && !memcmp(&addr->sin6_addr.s6_addr,
361 &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr.s6_addr,
362 sizeof(addr->sin6_addr.s6_addr))) {
363 local = 1;
364 break;
367 if (ifa->ifa_addr->sa_family == AF_INET
368 && !memcmp(&((struct sockaddr_in *) &addr)->sin_addr.s_addr,
369 &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr,
370 sizeof(((struct sockaddr_in *) &addr)->sin_addr.s_addr))) {
371 local = 1;
372 break;
376 freeifaddrs(ifaddrs);
379 return local;
381 #endif /* CONFIG_IPV6 */
383 static inline int
384 check_if_local_address4(struct sockaddr_in *addr)
386 struct ifaddrs *ifaddrs;
387 int local = (ntohl(addr->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
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_INET) continue;
398 if (!memcmp(&addr->sin_addr.s_addr,
399 &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr,
400 sizeof(addr->sin_addr.s_addr))) {
401 local = 1;
402 break;
406 freeifaddrs(ifaddrs);
409 return local;
413 void
414 complete_connect_socket(struct socket *socket, struct uri *uri,
415 socket_connect_T done)
417 struct connect_info *connect_info = socket->connect_info;
419 /* This is a special case used by the HTTP implementation to acquire an
420 * SSL link for handling CONNECT requests. */
421 if (!connect_info) {
422 assert(uri && socket);
423 connect_info = init_connection_info(uri, socket, done);
424 if (!connect_info) {
425 socket->ops->done(socket, S_OUT_OF_MEM);
426 return;
429 socket->connect_info = connect_info;
432 #ifdef CONFIG_SSL
433 /* Check if the connection should run over an encrypted link */
434 if (socket->need_ssl
435 && !socket->ssl
436 && ssl_connect(socket) < 0)
437 return;
438 #endif
440 if (connect_info->done)
441 connect_info->done(socket);
443 done_connection_info(socket);
446 /* Select handler which is set for the socket descriptor when connect() has
447 * indicated (via errno) that it is in progress. On completion this handler gets
448 * called. */
449 static void
450 connected(struct socket *socket)
452 int err = 0;
453 int len = sizeof(err);
455 assertm(socket->connect_info, "Lost connect_info!");
456 if_assert_failed return;
458 if (getsockopt(socket->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) == 0) {
459 /* Why does EMX return so large values? */
460 if (err >= 10000) err -= 10000;
461 } else {
462 /* getsockopt() failed */
463 if (errno > 0)
464 err = errno;
465 else
466 err = -(S_STATE);
469 if (err > 0) {
470 /* There are maybe still some more candidates. */
471 connect_socket(socket, -err);
472 return;
475 complete_connect_socket(socket, NULL, NULL);
478 void
479 connect_socket(struct socket *csocket, enum connection_state state)
481 int sock = -1;
482 struct connect_info *connect_info = csocket->connect_info;
483 int i;
484 int trno = connect_info->triedno;
485 int only_local = get_cmd_opt_bool("localhost");
486 int saved_errno = 0;
487 int at_least_one_remote_ip = 0;
488 /* We tried something but we failed in such a way that we would rather
489 * prefer the connection to retain the information about previous
490 * failures. That is, we i.e. decided we are forbidden to even think
491 * about such a connection attempt.
492 * XXX: Unify with @local_only handling? --pasky */
493 int silent_fail = 0;
495 csocket->ops->set_state(csocket, state);
497 /* Clear handlers, the connection to the previous RR really timed
498 * out and doesn't interest us anymore. */
499 if (csocket->fd >= 0)
500 close_socket(csocket);
502 for (i = connect_info->triedno + 1; i < connect_info->addrno; i++) {
503 #ifdef CONFIG_IPV6
504 struct sockaddr_in6 addr = *((struct sockaddr_in6 *) &connect_info->addr[i]);
505 #else
506 struct sockaddr_in addr = *((struct sockaddr_in *) &connect_info->addr[i]);
507 #endif
508 int family;
509 int force_family = connect_info->ip_family;
511 #ifdef CONFIG_IPV6
512 family = addr.sin6_family;
513 #else
514 family = addr.sin_family;
515 #endif
517 connect_info->triedno++;
519 if (only_local) {
520 int local = 0;
521 #ifdef CONFIG_IPV6
522 if (addr.sin6_family == AF_INET6)
523 local = check_if_local_address6((struct sockaddr_in6 *) &addr);
524 else
525 #endif
526 local = check_if_local_address4((struct sockaddr_in *) &addr);
528 /* This forbids connections to anything but local, if option is set. */
529 if (!local) {
530 at_least_one_remote_ip = 1;
531 continue;
535 #ifdef CONFIG_IPV6
536 if (family == AF_INET6 && (!get_opt_bool("connection.try_ipv6") || (force_family && force_family != 6))) {
537 silent_fail = 1;
538 continue;
539 } else
540 #endif
541 if (family == AF_INET && (!get_opt_bool("connection.try_ipv4") || (force_family && force_family != 4))) {
542 silent_fail = 1;
543 continue;
545 silent_fail = 0;
547 sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
548 if (sock == -1) {
549 if (errno && !saved_errno) saved_errno = errno;
550 continue;
553 if (set_nonblocking_fd(sock) < 0) {
554 if (errno && !saved_errno) saved_errno = errno;
555 close(sock);
556 continue;
558 csocket->fd = sock;
560 #ifdef CONFIG_IPV6
561 addr.sin6_port = htons(connect_info->port);
562 #else
563 addr.sin_port = htons(connect_info->port);
564 #endif
566 /* We can set csocket->protocol_family here even if the connection
567 * will fail, as we will use it only when it will be successfully
568 * established. At least I hope that noone else will want to do
569 * something else ;-). --pasky */
571 #ifdef CONFIG_IPV6
572 if (addr.sin6_family == AF_INET6) {
573 if (connect(sock, (struct sockaddr *) &addr,
574 sizeof(struct sockaddr_in6)) == 0) {
575 /* Success */
576 csocket->protocol_family = 1;
577 complete_connect_socket(csocket, NULL, NULL);
578 return;
580 } else
581 #endif
583 if (connect(sock, (struct sockaddr *) &addr,
584 sizeof(struct sockaddr_in)) == 0) {
585 /* Success */
586 csocket->protocol_family = 0;
587 complete_connect_socket(csocket, NULL, NULL);
588 return;
592 if (errno == EALREADY
593 #ifdef EWOULDBLOCK
594 || errno == EWOULDBLOCK
595 #endif
596 || errno == EINPROGRESS) {
597 /* It will take some more time... */
598 set_handlers(sock, NULL, (select_handler_T) connected,
599 (select_handler_T) dns_exception, csocket);
600 csocket->ops->set_state(csocket, S_CONN);
601 return;
604 if (errno && !saved_errno) saved_errno = errno;
606 close(sock);
609 assert(i >= connect_info->addrno);
611 /* Tried everything, but it didn't help :(. */
613 if (only_local && !saved_errno && at_least_one_remote_ip) {
614 /* Yes we might hit a local address and fail in the process, but
615 * what matters is the last one because we do not know the
616 * previous one's errno, and the added complexity wouldn't
617 * really be worth it. */
618 csocket->ops->done(csocket, S_LOCAL_ONLY);
619 return;
622 /* Retry reporting the errno state only if we already tried something
623 * new. Else use the S_DNS _progress_ state to make sure that no
624 * download callbacks will report any errors. */
625 if (trno != connect_info->triedno && !silent_fail)
626 state = -errno;
627 else if (trno == -1 && silent_fail)
628 /* All failed. */
629 state = S_NO_FORCED_DNS;
631 csocket->ops->retry(csocket, state);
635 struct write_buffer {
636 /* A routine called when all the data is sent (therefore this is
637 * _different_ from read_buffer.done !). */
638 socket_write_T done;
640 int length;
641 int pos;
643 unsigned char data[1]; /* must be at end of struct */
646 static int
647 generic_write(struct socket *socket, unsigned char *data, int len)
649 int wr = safe_write(socket->fd, data, len);
651 if (!wr) return SOCKET_CANT_WRITE;
653 return wr < 0 ? SOCKET_SYSCALL_ERROR : wr;
656 static void
657 write_select(struct socket *socket)
659 struct write_buffer *wb = socket->write_buffer;
660 int wr;
662 assertm(wb, "write socket has no buffer");
663 if_assert_failed {
664 socket->ops->done(socket, S_INTERNAL);
665 return;
668 /* We are making some progress, therefore reset the timeout; ie. when
669 * uploading large files the time needed for all the data to be sent can
670 * easily exceed the timeout. */
671 socket->ops->set_timeout(socket, 0);
673 #if 0
674 printf("ws: %d\n",wb->length-wb->pos);
675 for (wr = wb->pos; wr < wb->length; wr++) printf("%c", wb->data[wr]);
676 printf("-\n");
677 #endif
679 #ifdef CONFIG_SSL
680 if (socket->ssl) {
681 wr = ssl_write(socket, wb->data + wb->pos, wb->length - wb->pos);
682 } else
683 #endif
685 assert(wb->length - wb->pos > 0);
686 wr = generic_write(socket, wb->data + wb->pos, wb->length - wb->pos);
689 switch (wr) {
690 case SOCKET_CANT_WRITE:
691 socket->ops->retry(socket, S_CANT_WRITE);
692 break;
694 case SOCKET_SYSCALL_ERROR:
695 socket->ops->retry(socket, -errno);
696 break;
698 case SOCKET_INTERNAL_ERROR:
699 /* The global errno variable is used for passing
700 * internal connection_state error value. */
701 socket->ops->done(socket, -errno);
702 break;
704 default:
705 if (wr < 0) break;
707 /*printf("wr: %d\n", wr);*/
708 wb->pos += wr;
710 if (wb->pos == wb->length) {
711 socket_write_T done = wb->done;
713 if (!socket->duplex) {
714 clear_handlers(socket->fd);
716 } else {
717 select_handler_T read_handler;
718 select_handler_T error_handler;
720 read_handler = get_handler(socket->fd, SELECT_HANDLER_READ);
721 error_handler = read_handler
722 ? (select_handler_T) exception
723 : NULL;
725 set_handlers(socket->fd, read_handler, NULL,
726 error_handler, socket);
729 mem_free_set(&socket->write_buffer, NULL);
730 done(socket);
735 void
736 write_to_socket(struct socket *socket, unsigned char *data, int len,
737 enum connection_state state, socket_write_T write_done)
739 select_handler_T read_handler;
740 struct write_buffer *wb;
742 debug_transfer_log(data, len);
744 assert(len > 0);
745 if_assert_failed return;
747 socket->ops->set_timeout(socket, 0);
749 wb = mem_alloc(sizeof(*wb) + len);
750 if (!wb) {
751 socket->ops->done(socket, S_OUT_OF_MEM);
752 return;
755 wb->length = len;
756 wb->pos = 0;
757 wb->done = write_done;
758 memcpy(wb->data, data, len);
759 mem_free_set(&socket->write_buffer, wb);
761 if (socket->duplex) {
762 read_handler = get_handler(socket->fd, SELECT_HANDLER_READ);
763 } else {
764 read_handler = NULL;
767 set_handlers(socket->fd, read_handler, (select_handler_T) write_select,
768 (select_handler_T) exception, socket);
769 socket->ops->set_state(socket, state);
772 #define RD_ALLOC_GR (2<<11) /* 4096 */
773 #define RD_MEM(rb) (sizeof(*(rb)) + 4 * RD_ALLOC_GR + RD_ALLOC_GR)
774 #define RD_SIZE(rb, len) ((RD_MEM(rb) + (len)) & ~(RD_ALLOC_GR - 1))
776 static ssize_t
777 generic_read(struct socket *socket, unsigned char *data, int len)
779 ssize_t rd = safe_read(socket->fd, data, len);
781 if (!rd) return SOCKET_CANT_READ;
783 return rd < 0 ? SOCKET_SYSCALL_ERROR : rd;
786 static void
787 read_select(struct socket *socket)
789 struct read_buffer *rb = socket->read_buffer;
790 ssize_t rd;
792 assertm(rb, "read socket has no buffer");
793 if_assert_failed {
794 socket->ops->done(socket, S_INTERNAL);
795 return;
798 /* We are making some progress, therefore reset the timeout; we do this
799 * for read_select() to avoid that the periodic calls to user handlers
800 * has to do it. */
801 socket->ops->set_timeout(socket, 0);
803 if (!socket->duplex)
804 clear_handlers(socket->fd);
806 if (!rb->freespace) {
807 int size = RD_SIZE(rb, rb->length);
809 rb = mem_realloc(rb, size);
810 if (!rb) {
811 socket->ops->done(socket, S_OUT_OF_MEM);
812 return;
814 rb->freespace = size - sizeof(*rb) - rb->length;
815 assert(rb->freespace > 0);
816 socket->read_buffer = rb;
819 #ifdef CONFIG_SSL
820 if (socket->ssl) {
821 rd = ssl_read(socket, rb->data + rb->length, rb->freespace);
822 } else
823 #endif
825 rd = generic_read(socket, rb->data + rb->length, rb->freespace);
828 switch (rd) {
829 #ifdef CONFIG_SSL
830 case SOCKET_SSL_WANT_READ:
831 read_from_socket(socket, rb, S_TRANS, rb->done);
832 break;
833 #endif
834 case SOCKET_CANT_READ:
835 if (socket->state != SOCKET_RETRY_ONCLOSE) {
836 socket->state = SOCKET_CLOSED;
837 rb->done(socket, rb);
838 break;
841 errno = -S_CANT_READ;
842 /* Fall-through */
844 case SOCKET_SYSCALL_ERROR:
845 socket->ops->retry(socket, -errno);
846 break;
848 case SOCKET_INTERNAL_ERROR:
849 socket->ops->done(socket, -errno);
850 break;
852 default:
853 debug_transfer_log(rb->data + rb->length, rd);
855 rb->length += rd;
856 rb->freespace -= rd;
857 assert(rb->freespace >= 0);
859 rb->done(socket, rb);
863 struct read_buffer *
864 alloc_read_buffer(struct socket *socket)
866 struct read_buffer *rb;
868 rb = mem_calloc(1, RD_SIZE(rb, 0));
869 if (!rb) {
870 socket->ops->done(socket, S_OUT_OF_MEM);
871 return NULL;
874 rb->freespace = RD_SIZE(rb, 0) - sizeof(*rb);
876 return rb;
879 #undef RD_ALLOC_GR
880 #undef RD_MEM
881 #undef RD_SIZE
883 void
884 read_from_socket(struct socket *socket, struct read_buffer *buffer,
885 enum connection_state state, socket_read_T done)
887 select_handler_T write_handler;
889 buffer->done = done;
891 socket->ops->set_timeout(socket, 0);
892 socket->ops->set_state(socket, state);
894 if (socket->read_buffer && buffer != socket->read_buffer)
895 mem_free(socket->read_buffer);
896 socket->read_buffer = buffer;
898 if (socket->duplex) {
899 write_handler = get_handler(socket->fd, SELECT_HANDLER_WRITE);
900 } else {
901 write_handler = NULL;
904 set_handlers(socket->fd, (select_handler_T) read_select, write_handler,
905 (select_handler_T) exception, socket);
908 static void
909 read_response_from_socket(struct socket *socket)
911 struct read_buffer *rb = alloc_read_buffer(socket);
913 if (rb) read_from_socket(socket, rb, S_SENT, socket->read_done);
916 void
917 request_from_socket(struct socket *socket, unsigned char *data, int datalen,
918 enum connection_state state, enum socket_state sock_state,
919 socket_read_T read_done)
921 socket->read_done = read_done;
922 socket->state = sock_state;
923 write_to_socket(socket, data, datalen, state,
924 read_response_from_socket);
927 void
928 kill_buffer_data(struct read_buffer *rb, int n)
930 assertm(n >= 0 && n <= rb->length, "bad number of bytes: %d", n);
931 if_assert_failed { rb->length = 0; return; }
933 if (!n) return; /* FIXME: We accept to kill 0 bytes... */
934 rb->length -= n;
935 memmove(rb->data, rb->data + n, rb->length);
936 rb->freespace += n;