10 #ifdef HAVE_NETINET_IN_H
11 #include <netinet/in.h> /* OS/2 needs this after sys/types.h */
13 #ifdef HAVE_SYS_SOCKET_H
14 #include <sys/socket.h> /* OS/2 needs this after sys/types.h */
17 #include <fcntl.h> /* OS/2 needs this after sys/types.h */
22 #ifdef HAVE_WS2TCPIP_H
23 #include <ws2tcpip.h> /* socklen_t for MinGW */
26 #ifdef HAVE_GETIFADDRS
34 #include <ifaddrs.h> /* getifaddrs() */
36 #endif /* HAVE_GETIFADDRS */
38 #ifdef HAVE_ARPA_INET_H
39 #include <arpa/inet.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. */
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. */
86 #define DEBUG_TRANSFER_LOGFILE "/tmp/log"
89 debug_transfer_log(unsigned char *data
, int len
)
91 int fd
= open(DEBUG_TRANSFER_LOGFILE
, O_WRONLY
| O_APPEND
| O_CREAT
, 0622);
96 write(fd
, data
, len
< 0 ? strlen(data
) : len
);
99 #undef DEBUG_TRANSFER_LOGFILE
102 #define debug_transfer_log(data, len)
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
);
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
);
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
;
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
)
174 close_socket(struct socket
*socket
)
176 if (socket
->fd
== -1) return;
178 if (socket
->ssl
) ssl_close(socket
);
181 clear_handlers(socket
->fd
);
186 dns_exception(struct socket
*socket
)
188 connect_socket(socket
, connection_state(S_EXCEPT
));
192 exception(struct socket
*socket
)
194 socket
->ops
->retry(socket
, connection_state(S_EXCEPT
));
199 timeout_socket(struct socket
*socket
)
201 if (!socket
->connect_info
) {
202 socket
->ops
->retry(socket
, connection_state(S_TIMEOUT
));
206 /* Is the DNS resolving still in progress? */
207 if (socket
->connect_info
->dnsquery
) {
208 socket
->ops
->done(socket
, connection_state(S_TIMEOUT
));
212 /* Try the next address, */
213 connect_socket(socket
, connection_state(S_TIMEOUT
));
215 /* Reset the timeout if connect_socket() started a new attempt
217 if (socket
->connect_info
)
218 socket
->ops
->set_timeout(socket
, connection_state(0));
224 dns_found(struct socket
*socket
, struct sockaddr_storage
*addr
, int addrlen
)
226 struct connect_info
*connect_info
= socket
->connect_info
;
230 socket
->ops
->done(socket
, connection_state(S_NO_DNS
));
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
));
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
));
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));
268 socket
->ops
->retry(socket
, connection_state(S_OUT_OF_MEM
));
272 connect_info
= init_connection_info(uri
, socket
, connect_done
);
275 socket
->ops
->retry(socket
, connection_state(S_OUT_OF_MEM
));
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
,
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
;
312 int syspf
; /* Protocol Family given to system, not EL_PF_... */
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
);
324 bind_addr
= (struct sockaddr
*) &bind_addr4
;
325 addrlen
= sizeof(bind_addr4
);
329 memset(pasv_addr
, 0, addrlen
);
330 memset(bind_addr
, 0, addrlen
);
332 /* Get our endpoint of the control socket */
334 if (getsockname(ctrl_socket
->fd
, pasv_addr
, &len
)) {
336 if (sock
!= -1) close(sock
);
337 ctrl_socket
->ops
->retry(ctrl_socket
,
338 connection_state_for_errno(errno
));
342 /* Get a passive socket */
344 sock
= socket(syspf
, SOCK_STREAM
, IPPROTO_TCP
);
348 /* Set it non-blocking */
350 if (set_nonblocking_fd(sock
) < 0)
353 /* Bind it to some port */
355 memcpy(bind_addr
, pasv_addr
, addrlen
);
357 if (ctrl_socket
->protocol_family
== EL_PF_INET6
)
358 bind_addr6
.sin6_port
= 0;
361 bind_addr4
.sin_port
= 0;
363 if (bind(sock
, bind_addr
, addrlen
))
366 /* Get our endpoint of the passive socket and save it to port */
369 if (getsockname(sock
, pasv_addr
, &len
))
377 set_ip_tos_throughput(sock
);
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
)) {
392 for (ifa
= ifaddrs
; ifa
; ifa
= ifa
->ifa_next
) {
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
))) {
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
))) {
413 freeifaddrs(ifaddrs
);
418 #endif /* CONFIG_IPV6 */
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
)) {
429 for (ifa
= ifaddrs
; ifa
; ifa
= ifa
->ifa_next
) {
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
))) {
443 freeifaddrs(ifaddrs
);
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. */
463 add_blacklist_entry(connect_info
->uri
,
464 SERVER_BLACKLIST_NO_TLS
);
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. */
473 assert(uri
&& socket
);
474 connect_info
= init_connection_info(uri
, socket
, done
);
476 socket
->ops
->done(socket
, connection_state(S_OUT_OF_MEM
));
480 socket
->connect_info
= connect_info
;
484 /* Check if the connection should run over an encrypted link */
487 && ssl_connect(socket
) < 0)
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
501 connected(struct socket
*socket
)
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;
514 state
= connection_state_for_errno(err
);
516 state
= connection_state(0);
518 /* getsockopt() failed */
520 state
= connection_state_for_errno(errno
);
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
);
531 complete_connect_socket(socket
, NULL
, NULL
);
535 connect_socket(struct socket
*csocket
, struct connection_state state
)
538 struct connect_info
*connect_info
= csocket
->connect_info
;
540 int trno
= connect_info
->triedno
;
541 int only_local
= get_cmd_opt_bool("localhost");
543 int at_least_one_remote_ip
= 0;
545 int try_ipv6
= get_opt_bool("connection.try_ipv6", NULL
);
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 */
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
++) {
564 struct sockaddr_in6 addr
= *((struct sockaddr_in6
*) &connect_info
->addr
[i
]);
565 int family
= addr
.sin6_family
;
567 struct sockaddr_in addr
= *((struct sockaddr_in
*) &connect_info
->addr
[i
]);
568 int family
= addr
.sin_family
;
571 int force_family
= connect_info
->ip_family
;
573 connect_info
->triedno
++;
578 if (family
== AF_INET6
)
579 local
= check_if_local_address6((struct sockaddr_in6
*) &addr
);
582 local
= check_if_local_address4((struct sockaddr_in
*) &addr
);
584 /* This forbids connections to anything but local, if option is set. */
586 at_least_one_remote_ip
= 1;
592 if (family
== AF_INET6
) {
593 if (!try_ipv6
|| (force_family
&& force_family
!= 6)) {
601 if (family
== AF_INET
) {
602 if (!try_ipv4
|| (force_family
&& force_family
!= 4)) {
613 sock
= socket(pf
, SOCK_STREAM
, IPPROTO_TCP
);
615 if (errno
&& !saved_errno
) saved_errno
= errno
;
619 if (set_nonblocking_fd(sock
) < 0) {
620 if (errno
&& !saved_errno
) saved_errno
= errno
;
627 addr
.sin6_port
= htons(connect_info
->port
);
629 addr
.sin_port
= htons(connect_info
->port
);
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. */
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) {
644 complete_connect_socket(csocket
, NULL
, NULL
);
650 csocket
->protocol_family
= EL_PF_INET
;
651 if (connect(sock
, (struct sockaddr
*) &addr
,
652 sizeof(struct sockaddr_in
)) == 0) {
654 complete_connect_socket(csocket
, NULL
, NULL
);
659 if (errno
== EALREADY
661 || errno
== EWOULDBLOCK
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
));
671 if (errno
&& !saved_errno
) saved_errno
= errno
;
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
));
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
)
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 !). */
710 unsigned char data
[1]; /* must be at end of struct */
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
;
722 if (errno
== EWOULDBLOCK
) return SOCKET_CANT_WRITE
;
724 return SOCKET_SYSCALL_ERROR
;
730 write_select(struct socket
*socket
)
732 struct write_buffer
*wb
= socket
->write_buffer
;
735 assertm(wb
!= NULL
, "write socket has no buffer");
737 socket
->ops
->done(socket
, connection_state(S_INTERNAL
));
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));
747 printf("ws: %d\n",wb
->length
-wb
->pos
);
748 for (wr
= wb
->pos
; wr
< wb
->length
; wr
++) printf("%c", wb
->data
[wr
]);
754 wr
= ssl_write(socket
, wb
->data
+ wb
->pos
, wb
->length
- wb
->pos
);
758 assert(wb
->length
- wb
->pos
> 0);
759 wr
= generic_write(socket
, wb
->data
+ wb
->pos
, wb
->length
- wb
->pos
);
763 case SOCKET_CANT_WRITE
:
764 socket
->ops
->retry(socket
, connection_state(S_CANT_WRITE
));
767 case SOCKET_SYSCALL_ERROR
:
768 socket
->ops
->retry(socket
, connection_state_for_errno(errno
));
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
));
780 /*printf("wr: %d\n", wr);*/
783 if (wb
->pos
== wb
->length
) {
784 socket_write_T done
= wb
->done
;
786 if (!socket
->duplex
) {
787 clear_handlers(socket
->fd
);
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
798 set_handlers(socket
->fd
, read_handler
, NULL
,
799 error_handler
, socket
);
802 mem_free_set(&socket
->write_buffer
, NULL
);
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
);
818 if_assert_failed
return;
820 socket
->ops
->set_timeout(socket
, connection_state(0));
822 wb
= mem_alloc(sizeof(*wb
) + len
);
824 socket
->ops
->done(socket
, connection_state(S_OUT_OF_MEM
));
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
);
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))
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
;
858 if (errno
== EWOULDBLOCK
) return SOCKET_CANT_READ
;
860 return SOCKET_SYSCALL_ERROR
;
866 read_select(struct socket
*socket
)
868 struct read_buffer
*rb
= socket
->read_buffer
;
871 assertm(rb
!= NULL
, "read socket has no buffer");
873 socket
->ops
->done(socket
, connection_state(S_INTERNAL
));
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
880 socket
->ops
->set_timeout(socket
, connection_state(0));
883 clear_handlers(socket
->fd
);
885 if (!rb
->freespace
) {
886 int size
= RD_SIZE(rb
, rb
->length
);
888 rb
= mem_realloc(rb
, size
);
890 socket
->ops
->done(socket
, connection_state(S_OUT_OF_MEM
));
893 rb
->freespace
= size
- sizeof(*rb
) - rb
->length
;
894 assert(rb
->freespace
> 0);
895 socket
->read_buffer
= rb
;
900 rd
= ssl_read(socket
, rb
->data
+ rb
->length
, rb
->freespace
);
904 rd
= generic_read(socket
, rb
->data
+ rb
->length
, rb
->freespace
);
909 case SOCKET_SSL_WANT_READ
:
910 read_from_socket(socket
, rb
, connection_state(S_TRANS
), rb
->done
);
913 case SOCKET_CANT_READ
:
914 if (socket
->state
!= SOCKET_RETRY_ONCLOSE
) {
915 socket
->state
= SOCKET_CLOSED
;
916 rb
->done(socket
, rb
);
920 socket
->ops
->retry(socket
, connection_state(S_CANT_READ
));
923 case SOCKET_SYSCALL_ERROR
:
924 socket
->ops
->retry(socket
, connection_state_for_errno(errno
));
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
));
934 debug_transfer_log(rb
->data
+ rb
->length
, rd
);
938 assert(rb
->freespace
>= 0);
940 rb
->done(socket
, rb
);
945 alloc_read_buffer(struct socket
*socket
)
947 struct read_buffer
*rb
;
949 rb
= mem_calloc(1, RD_SIZE(rb
, 0));
951 socket
->ops
->done(socket
, connection_state(S_OUT_OF_MEM
));
955 rb
->freespace
= RD_SIZE(rb
, 0) - sizeof(*rb
);
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
;
973 add_to_list(socket_weak_refs
, &ref
);
977 socket
->ops
->set_timeout(socket
, connection_state(0));
978 socket
->ops
->set_state(socket
, state
);
981 if (ref
.socket
== NULL
) {
982 /* socket->ops->set_state deleted the socket. */
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
);
995 write_handler
= NULL
;
998 set_handlers(socket
->fd
, (select_handler_T
) read_select
, write_handler
,
999 (select_handler_T
) exception
, socket
);
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
),
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
);
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... */
1030 memmove(rb
->data
, rb
->data
+ n
, rb
->length
);