1 /* Copyright 2001,2002,2003 Roger Dingledine, Matej Pfajfar. */
2 /* See LICENSE for licensing information */
7 /********* START VARIABLES **********/
9 extern or_options_t options
; /* command-line and config-file options */
11 extern int global_read_bucket
;
13 char *conn_type_to_string
[] = {
15 "OP listener", /* 1 */
17 "OR listener", /* 3 */
20 "App listener",/* 6 */
22 "Dir listener",/* 8 */
24 "DNS worker", /* 10 */
25 "CPU worker", /* 11 */
28 char *conn_state_to_string
[][_CONN_TYPE_MAX
+1] = {
29 { NULL
}, /* no type associated with 0 */
30 { NULL
}, /* op listener, obsolete */
31 { NULL
}, /* op, obsolete */
32 { "ready" }, /* or listener, 0 */
34 "connect()ing", /* 1 */
35 "handshaking", /* 2 */
38 "waiting for dest info", /* 1 */
41 { "ready" }, /* app listener, 0 */
46 "awaiting dest info", /* app, 4 */
47 "waiting for safe circuit", /* 5 */
48 "waiting for connected", /* 6 */
50 { "ready" }, /* dir listener, 0 */
52 "connecting (fetch)", /* 1 */
53 "connecting (upload)", /* 2 */
54 "client sending fetch", /* 3 */
55 "client sending upload", /* 4 */
56 "client reading fetch", /* 5 */
57 "client reading upload", /* 6 */
58 "awaiting command", /* 7 */
60 { "", /* dns worker, 0 */
63 { "", /* cpu worker, 0 */
65 "busy with onion", /* 2 */
66 "busy with handshake" }, /* 3 */
69 /********* END VARIABLES ************/
71 static int connection_init_accepted_conn(connection_t
*conn
);
72 static int connection_handle_listener_read(connection_t
*conn
, int new_type
);
74 /**************************************************************/
76 connection_t
*connection_new(int type
) {
78 time_t now
= time(NULL
);
80 conn
= tor_malloc_zero(sizeof(connection_t
));
81 conn
->magic
= CONNECTION_MAGIC
;
82 conn
->s
= -1; /* give it a default of 'not used' */
86 if(!connection_is_listener(conn
)) { /* listeners never use their buf */
87 conn
->inbuf
= buf_new();
88 conn
->outbuf
= buf_new();
90 if (type
== CONN_TYPE_AP
) {
91 conn
->socks_request
= tor_malloc_zero(sizeof(socks_request_t
));
94 conn
->next_circ_id
= crypto_pseudo_rand_int(1<<15);
96 conn
->timestamp_created
= now
;
97 conn
->timestamp_lastread
= now
;
98 conn
->timestamp_lastwritten
= now
;
103 void connection_free(connection_t
*conn
) {
105 assert(conn
->magic
== CONNECTION_MAGIC
);
107 if(!connection_is_listener(conn
)) {
108 buf_free(conn
->inbuf
);
109 buf_free(conn
->outbuf
);
111 tor_free(conn
->address
);
113 if(connection_speaks_cells(conn
)) {
114 directory_set_dirty();
116 tor_tls_free(conn
->tls
);
119 if (conn
->onion_pkey
)
120 crypto_free_pk_env(conn
->onion_pkey
);
122 crypto_free_pk_env(conn
->link_pkey
);
123 if (conn
->identity_pkey
)
124 crypto_free_pk_env(conn
->identity_pkey
);
125 tor_free(conn
->nickname
);
126 tor_free(conn
->socks_request
);
129 log_fn(LOG_INFO
,"closing fd %d.",conn
->s
);
132 memset(conn
, 0xAA, sizeof(connection_t
)); /* poison memory */
136 void connection_free_all(void) {
138 connection_t
**carray
;
140 get_connection_array(&carray
,&n
);
142 connection_free(carray
[i
]);
145 int connection_create_listener(char *bindaddress
, uint16_t bindport
, int type
) {
146 struct sockaddr_in bindaddr
; /* where to bind */
147 struct hostent
*rent
;
149 int s
; /* the socket we're going to make */
152 memset(&bindaddr
,0,sizeof(struct sockaddr_in
));
153 bindaddr
.sin_family
= AF_INET
;
154 bindaddr
.sin_port
= htons(bindport
);
155 rent
= gethostbyname(bindaddress
);
157 log_fn(LOG_WARN
,"Can't resolve BindAddress %s",bindaddress
);
160 if(rent
->h_length
!= 4)
161 return -1; /* XXX complain */
162 memcpy(&(bindaddr
.sin_addr
.s_addr
),rent
->h_addr
,rent
->h_length
);
164 s
= socket(PF_INET
,SOCK_STREAM
,IPPROTO_TCP
);
166 log_fn(LOG_WARN
,"Socket creation failed.");
170 setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, &one
, sizeof(one
));
172 if(bind(s
,(struct sockaddr
*)&bindaddr
,sizeof(bindaddr
)) < 0) {
173 log_fn(LOG_WARN
,"Could not bind to port %u: %s",bindport
,strerror(errno
));
177 if(listen(s
,SOMAXCONN
) < 0) {
178 log_fn(LOG_WARN
,"Could not listen on port %u: %s",bindport
,strerror(errno
));
182 set_socket_nonblocking(s
);
184 conn
= connection_new(type
);
187 if(connection_add(conn
) < 0) { /* no space, forget it */
188 log_fn(LOG_WARN
,"connection_add failed. Giving up.");
189 connection_free(conn
);
193 log_fn(LOG_DEBUG
,"%s listening on port %u.",conn_type_to_string
[type
], bindport
);
195 conn
->state
= LISTENER_STATE_READY
;
196 connection_start_reading(conn
);
201 static int connection_handle_listener_read(connection_t
*conn
, int new_type
) {
202 int news
; /* the new socket */
203 connection_t
*newconn
;
204 struct sockaddr_in remote
; /* information about the remote peer when connecting to other routers */
205 int remotelen
= sizeof(struct sockaddr_in
); /* length of the remote address */
210 news
= accept(conn
->s
,(struct sockaddr
*)&remote
,&remotelen
);
211 if (news
== -1) { /* accept() error */
212 if(ERRNO_EAGAIN(errno
)) {
214 e
= correct_socket_errno(conn
->s
);
218 return 0; /* he hung up before we could accept(). that's fine. */
221 /* else there was a real error. */
222 log_fn(LOG_WARN
,"accept() failed. Closing listener.");
225 log(LOG_INFO
,"Connection accepted on socket %d (child of fd %d).",news
, conn
->s
);
227 set_socket_nonblocking(news
);
229 newconn
= connection_new(new_type
);
232 newconn
->address
= tor_strdup(inet_ntoa(remote
.sin_addr
)); /* remember the remote address */
233 newconn
->addr
= ntohl(remote
.sin_addr
.s_addr
);
234 newconn
->port
= ntohs(remote
.sin_port
);
236 if(connection_add(newconn
) < 0) { /* no space, forget it */
237 connection_free(newconn
);
238 return 0; /* no need to tear down the parent */
241 if(connection_init_accepted_conn(newconn
) < 0) {
242 newconn
->marked_for_close
= 1;
248 static int connection_init_accepted_conn(connection_t
*conn
) {
250 connection_start_reading(conn
);
254 return connection_tls_start_handshake(conn
, 1);
256 conn
->state
= AP_CONN_STATE_SOCKS_WAIT
;
259 conn
->state
= DIR_CONN_STATE_SERVER_COMMAND_WAIT
;
265 /* take conn, make a nonblocking socket; try to connect to
266 * addr:port (they arrive in *host order*). If fail, return -1. Else
267 * assign s to conn->s: if connected return 1, if eagain return 0.
268 * address is used to make the logs useful.
270 int connection_connect(connection_t
*conn
, char *address
, uint32_t addr
, uint16_t port
) {
272 struct sockaddr_in dest_addr
;
274 s
=socket(PF_INET
,SOCK_STREAM
,IPPROTO_TCP
);
276 log_fn(LOG_WARN
,"Error creating network socket.");
279 set_socket_nonblocking(s
);
281 memset(&dest_addr
,0,sizeof(dest_addr
));
282 dest_addr
.sin_family
= AF_INET
;
283 dest_addr
.sin_port
= htons(port
);
284 dest_addr
.sin_addr
.s_addr
= htonl(addr
);
286 log_fn(LOG_DEBUG
,"Connecting to %s:%u.",address
,port
);
288 if(connect(s
,(struct sockaddr
*)&dest_addr
,sizeof(dest_addr
)) < 0) {
289 if(!ERRNO_CONN_EINPROGRESS(errno
)) {
291 log_fn(LOG_INFO
,"Connect() to %s:%u failed: %s",address
,port
,strerror(errno
));
295 /* it's in progress. set state appropriately and return. */
297 log_fn(LOG_DEBUG
,"connect in progress, socket %d.",s
);
302 /* it succeeded. we're connected. */
303 log_fn(LOG_INFO
,"Connection to %s:%u established.",address
,port
);
308 static void listener_close_if_present(int type
) {
309 connection_t
*conn
= connection_get_by_type(type
);
313 conn
->marked_for_close
= 1;
317 /* start all connections that should be up but aren't */
318 int retry_all_connections(void) {
321 router_retry_connections();
325 listener_close_if_present(CONN_TYPE_OR_LISTENER
);
326 if(connection_create_listener(options
.ORBindAddress
, options
.ORPort
,
327 CONN_TYPE_OR_LISTENER
) < 0)
331 if(options
.DirPort
) {
332 listener_close_if_present(CONN_TYPE_DIR_LISTENER
);
333 if(connection_create_listener(options
.DirBindAddress
, options
.DirPort
,
334 CONN_TYPE_DIR_LISTENER
) < 0)
338 if(options
.SocksPort
) {
339 listener_close_if_present(CONN_TYPE_AP_LISTENER
);
340 if(connection_create_listener(options
.SocksBindAddress
, options
.SocksPort
,
341 CONN_TYPE_AP_LISTENER
) < 0)
348 int connection_handle_read(connection_t
*conn
) {
350 conn
->timestamp_lastread
= time(NULL
);
353 case CONN_TYPE_OR_LISTENER
:
354 return connection_handle_listener_read(conn
, CONN_TYPE_OR
);
355 case CONN_TYPE_AP_LISTENER
:
356 return connection_handle_listener_read(conn
, CONN_TYPE_AP
);
357 case CONN_TYPE_DIR_LISTENER
:
358 return connection_handle_listener_read(conn
, CONN_TYPE_DIR
);
361 if(connection_read_to_buf(conn
) < 0) {
362 if(conn
->type
== CONN_TYPE_DIR
&&
363 (conn
->state
== DIR_CONN_STATE_CONNECTING_FETCH
||
364 conn
->state
== DIR_CONN_STATE_CONNECTING_UPLOAD
)) {
365 /* it's a directory server and connecting failed: forget about this router */
366 /* XXX I suspect pollerr may make Windows not get to this point. :( */
367 router_mark_as_down(conn
->nickname
);
371 if(connection_process_inbuf(conn
) < 0) {
372 // log_fn(LOG_DEBUG,"connection_process_inbuf returned -1.");
378 /* return -1 if we want to break conn, else return 0 */
379 int connection_read_to_buf(connection_t
*conn
) {
383 if(options
.LinkPadding
) {
384 at_most
= global_read_bucket
;
386 /* do a rudimentary round-robin so one connection can't hog a thickpipe */
387 if(connection_speaks_cells(conn
)) {
388 at_most
= 32*(CELL_NETWORK_SIZE
);
390 at_most
= 32*(RELAY_PAYLOAD_SIZE
);
393 if(at_most
> global_read_bucket
)
394 at_most
= global_read_bucket
;
397 if(connection_speaks_cells(conn
) && conn
->state
!= OR_CONN_STATE_CONNECTING
) {
398 if(conn
->state
== OR_CONN_STATE_HANDSHAKING
)
399 return connection_tls_continue_handshake(conn
);
401 /* else open, or closing */
402 if(at_most
> conn
->receiver_bucket
)
403 at_most
= conn
->receiver_bucket
;
404 result
= read_to_buf_tls(conn
->tls
, at_most
, conn
->inbuf
);
409 log_fn(LOG_INFO
,"tls error. breaking.");
410 return -1; /* XXX deal with close better */
411 case TOR_TLS_WANTWRITE
:
412 connection_start_writing(conn
);
414 case TOR_TLS_WANTREAD
: /* we're already reading */
415 case TOR_TLS_DONE
: /* no data read, so nothing to process */
419 result
= read_to_buf(conn
->s
, at_most
, conn
->inbuf
,
420 &conn
->inbuf_reached_eof
);
422 // log(LOG_DEBUG,"connection_read_to_buf(): read_to_buf returned %d.",read_result);
428 global_read_bucket
-= result
; assert(global_read_bucket
>= 0);
429 if(global_read_bucket
== 0) {
430 log_fn(LOG_DEBUG
,"global bucket exhausted. Pausing.");
431 conn
->wants_to_read
= 1;
432 connection_stop_reading(conn
);
435 if(connection_speaks_cells(conn
) && conn
->state
== OR_CONN_STATE_OPEN
) {
436 conn
->receiver_bucket
-= result
; assert(conn
->receiver_bucket
>= 0);
437 if(conn
->receiver_bucket
== 0) {
438 log_fn(LOG_DEBUG
,"receiver bucket exhausted. Pausing.");
439 conn
->wants_to_read
= 1;
440 connection_stop_reading(conn
);
447 int connection_fetch_from_buf(char *string
, int len
, connection_t
*conn
) {
448 return fetch_from_buf(string
, len
, conn
->inbuf
);
451 int connection_find_on_inbuf(char *string
, int len
, connection_t
*conn
) {
452 return find_on_inbuf(string
, len
, conn
->inbuf
);
455 int connection_wants_to_flush(connection_t
*conn
) {
456 return conn
->outbuf_flushlen
;
459 int connection_outbuf_too_full(connection_t
*conn
) {
460 return (conn
->outbuf_flushlen
> 10*CELL_PAYLOAD_SIZE
);
463 /* return -1 if you want to break the conn, else return 0 */
464 int connection_handle_write(connection_t
*conn
) {
466 if(connection_is_listener(conn
)) {
467 log_fn(LOG_WARN
,"Got a listener socket. Can't happen!");
471 conn
->timestamp_lastwritten
= time(NULL
);
473 if(connection_speaks_cells(conn
) && conn
->state
!= OR_CONN_STATE_CONNECTING
) {
474 if(conn
->state
== OR_CONN_STATE_HANDSHAKING
) {
475 connection_stop_writing(conn
);
476 return connection_tls_continue_handshake(conn
);
479 /* else open, or closing */
480 switch(flush_buf_tls(conn
->tls
, conn
->outbuf
, &conn
->outbuf_flushlen
)) {
483 log_fn(LOG_INFO
,"tls error. breaking.");
484 return -1; /* XXX deal with close better */
485 case TOR_TLS_WANTWRITE
:
486 log_fn(LOG_DEBUG
,"wanted write.");
487 /* we're already writing */
489 case TOR_TLS_WANTREAD
:
490 /* Make sure to avoid a loop if the receive buckets are empty. */
491 log_fn(LOG_DEBUG
,"wanted read.");
492 if(!connection_is_reading(conn
)) {
493 connection_stop_writing(conn
);
494 conn
->wants_to_write
= 1;
495 /* we'll start reading again when the next second arrives,
496 * and then also start writing again.
499 /* else no problem, we're already reading */
501 /* case TOR_TLS_DONE:
502 * for TOR_TLS_DONE, fall through to check if the flushlen
503 * is empty, so we can stop writing.
507 if(flush_buf(conn
->s
, conn
->outbuf
, &conn
->outbuf_flushlen
) < 0)
509 /* conns in CONNECTING state will fall through... */
512 if(!connection_wants_to_flush(conn
)) /* it's done flushing */
513 if(connection_finished_flushing(conn
) < 0) /* ...and get handled here. */
519 void connection_write_to_buf(const char *string
, int len
, connection_t
*conn
) {
521 if(!len
|| conn
->marked_for_close
)
524 if(write_to_buf(string
, len
, conn
->outbuf
) < 0) {
525 log_fn(LOG_WARN
,"write_to_buf failed. Closing connection (fd %d).", conn
->s
);
526 conn
->marked_for_close
= 1;
530 connection_start_writing(conn
);
531 #define MIN_TLS_FLUSHLEN 15872
532 /* openssl tls record size is 16383, this is close. The goal here is to
533 * push data out as soon as we know there's enough for a tls record, so
534 * during periods of high load we won't read the entire megabyte from
535 * input before pushing any data out. */
536 if(connection_speaks_cells(conn
) &&
537 conn
->outbuf_flushlen
< MIN_TLS_FLUSHLEN
&&
538 conn
->outbuf_flushlen
+len
>= MIN_TLS_FLUSHLEN
) {
539 len
-= (MIN_TLS_FLUSHLEN
- conn
->outbuf_flushlen
);
540 conn
->outbuf_flushlen
= MIN_TLS_FLUSHLEN
;
541 if(connection_handle_write(conn
) < 0) {
542 conn
->marked_for_close
= 1;
543 log_fn(LOG_WARN
,"flushing failed.");
546 if(len
> 0) { /* if there's any left over */
547 conn
->outbuf_flushlen
+= len
;
548 connection_start_writing(conn
);
549 /* because connection_handle_write() above might have stopped writing */
553 connection_t
*connection_exact_get_by_addr_port(uint32_t addr
, uint16_t port
) {
556 connection_t
**carray
;
558 get_connection_array(&carray
,&n
);
561 if(conn
->addr
== addr
&& conn
->port
== port
&& !conn
->marked_for_close
)
567 connection_t
*connection_twin_get_by_addr_port(uint32_t addr
, uint16_t port
) {
568 /* Find a connection to the router described by addr and port,
569 * or alternately any router which knows its key.
570 * This connection *must* be in 'open' state.
571 * If not, return NULL.
575 routerinfo_t
*router
;
576 connection_t
**carray
;
578 /* first check if it's there exactly */
579 conn
= connection_exact_get_by_addr_port(addr
,port
);
580 if(conn
&& connection_state_is_open(conn
)) {
581 log(LOG_INFO
,"connection_twin_get_by_addr_port(): Found exact match.");
585 /* now check if any of the other open connections are a twin for this one */
587 router
= router_get_by_addr_port(addr
,port
);
591 get_connection_array(&carray
,&n
);
595 if(connection_state_is_open(conn
) &&
596 !crypto_pk_cmp_keys(conn
->onion_pkey
, router
->onion_pkey
)) {
597 log(LOG_INFO
,"connection_twin_get_by_addr_port(): Found twin (%s).",conn
->address
);
604 connection_t
*connection_get_by_type(int type
) {
607 connection_t
**carray
;
609 get_connection_array(&carray
,&n
);
612 if(conn
->type
== type
&& !conn
->marked_for_close
)
618 connection_t
*connection_get_by_type_state(int type
, int state
) {
621 connection_t
**carray
;
623 get_connection_array(&carray
,&n
);
626 if(conn
->type
== type
&& conn
->state
== state
&& !conn
->marked_for_close
)
632 connection_t
*connection_get_by_type_state_lastwritten(int type
, int state
) {
634 connection_t
*conn
, *best
=NULL
;
635 connection_t
**carray
;
637 get_connection_array(&carray
,&n
);
640 if(conn
->type
== type
&& conn
->state
== state
&& !conn
->marked_for_close
)
641 if(!best
|| conn
->timestamp_lastwritten
< best
->timestamp_lastwritten
)
647 int connection_receiver_bucket_should_increase(connection_t
*conn
) {
650 if(!connection_speaks_cells(conn
))
651 return 0; /* edge connections don't use receiver_buckets */
652 if(conn
->state
!= OR_CONN_STATE_OPEN
)
653 return 0; /* only open connections play the rate limiting game */
655 assert(conn
->bandwidth
> 0);
656 if(conn
->receiver_bucket
> 9*conn
->bandwidth
)
662 int connection_is_listener(connection_t
*conn
) {
663 if(conn
->type
== CONN_TYPE_OR_LISTENER
||
664 conn
->type
== CONN_TYPE_AP_LISTENER
||
665 conn
->type
== CONN_TYPE_DIR_LISTENER
)
670 int connection_state_is_open(connection_t
*conn
) {
673 if(conn
->marked_for_close
)
676 if((conn
->type
== CONN_TYPE_OR
&& conn
->state
== OR_CONN_STATE_OPEN
) ||
677 (conn
->type
== CONN_TYPE_AP
&& conn
->state
== AP_CONN_STATE_OPEN
) ||
678 (conn
->type
== CONN_TYPE_EXIT
&& conn
->state
== EXIT_CONN_STATE_OPEN
))
684 int connection_send_destroy(uint16_t circ_id
, connection_t
*conn
) {
689 if(!connection_speaks_cells(conn
)) {
690 log_fn(LOG_INFO
,"CircID %d: At an edge. Marking connection for close.",
692 if(conn
->type
== CONN_TYPE_EXIT
&& conn
->state
== EXIT_CONN_STATE_RESOLVING
) {
693 log_fn(LOG_INFO
,"...and informing resolver we don't want the answer anymore.");
694 dns_cancel_pending_resolve(conn
->address
, conn
);
696 if(connection_edge_end(conn
, END_STREAM_REASON_DESTROY
, conn
->cpath_layer
) < 0)
697 log_fn(LOG_WARN
,"1: I called connection_edge_end redundantly.");
698 /* if they already sent a destroy, they know. XXX can just close? */
702 memset(&cell
, 0, sizeof(cell_t
));
703 cell
.circ_id
= circ_id
;
704 cell
.command
= CELL_DESTROY
;
705 log_fn(LOG_INFO
,"Sending destroy (circID %d).", circ_id
);
706 connection_or_write_cell_to_buf(&cell
, conn
);
710 int connection_process_inbuf(connection_t
*conn
) {
716 return connection_or_process_inbuf(conn
);
719 return connection_edge_process_inbuf(conn
);
721 return connection_dir_process_inbuf(conn
);
722 case CONN_TYPE_DNSWORKER
:
723 return connection_dns_process_inbuf(conn
);
724 case CONN_TYPE_CPUWORKER
:
725 return connection_cpu_process_inbuf(conn
);
727 log_fn(LOG_WARN
,"got unexpected conn->type %d.", conn
->type
);
732 int connection_finished_flushing(connection_t
*conn
) {
736 // log_fn(LOG_DEBUG,"entered. Socket %u.", conn->s);
740 return connection_or_finished_flushing(conn
);
743 return connection_edge_finished_flushing(conn
);
745 return connection_dir_finished_flushing(conn
);
746 case CONN_TYPE_DNSWORKER
:
747 return connection_dns_finished_flushing(conn
);
748 case CONN_TYPE_CPUWORKER
:
749 return connection_cpu_finished_flushing(conn
);
751 log_fn(LOG_WARN
,"got unexpected conn->type %d.", conn
->type
);
756 void assert_connection_ok(connection_t
*conn
, time_t now
)
759 assert(conn
->magic
== CONNECTION_MAGIC
);
761 assert(conn
->type
>= _CONN_TYPE_MIN
);
762 assert(conn
->type
<= _CONN_TYPE_MAX
);
764 if(conn
->outbuf_flushlen
> 0) {
765 assert(connection_is_writing(conn
) || conn
->wants_to_write
);
768 /* XXX check: wants_to_read, wants_to_write, s, poll_index,
769 * marked_for_close. */
772 if (!connection_is_listener(conn
)) {
774 assert(conn
->outbuf
);
777 assert(!now
|| conn
->timestamp_lastread
<= now
);
778 assert(!now
|| conn
->timestamp_lastwritten
<= now
);
779 assert(conn
->timestamp_created
<= conn
->timestamp_lastread
);
780 assert(conn
->timestamp_created
<= conn
->timestamp_lastwritten
);
782 /* XXX Fix this; no longer so.*/
784 if(conn
->type
!= CONN_TYPE_OR
&& conn
->type
!= CONN_TYPE_DIR
)
786 /* pkey is set if we're a dir client, or if we're an OR in state OPEN
787 * connected to another OR.
791 if (conn
->type
!= CONN_TYPE_OR
) {
794 if(conn
->state
== OR_CONN_STATE_OPEN
) {
795 assert(conn
->bandwidth
> 0);
796 assert(conn
->receiver_bucket
>= 0);
797 // assert(conn->receiver_bucket <= 10*conn->bandwidth);
799 assert(conn
->addr
&& conn
->port
);
800 assert(conn
->address
);
801 if (conn
->state
!= OR_CONN_STATE_CONNECTING
)
805 if (conn
->type
!= CONN_TYPE_EXIT
&& conn
->type
!= CONN_TYPE_AP
) {
806 assert(!conn
->stream_id
);
807 assert(!conn
->next_stream
);
808 assert(!conn
->cpath_layer
);
809 assert(!conn
->package_window
);
810 assert(!conn
->deliver_window
);
811 assert(!conn
->done_sending
);
812 assert(!conn
->done_receiving
);
814 if(conn
->type
== CONN_TYPE_AP
&& conn
->state
== AP_CONN_STATE_OPEN
)
815 assert(conn
->cpath_layer
);
816 if(conn
->cpath_layer
)
817 assert_cpath_layer_ok(conn
->cpath_layer
);
818 /* XXX unchecked: package window, deliver window. */
820 if (conn
->type
!= CONN_TYPE_AP
) {
821 assert(!conn
->socks_request
);
826 case CONN_TYPE_OR_LISTENER
:
827 case CONN_TYPE_AP_LISTENER
:
828 case CONN_TYPE_DIR_LISTENER
:
829 assert(conn
->state
== LISTENER_STATE_READY
);
832 assert(conn
->state
>= _OR_CONN_STATE_MIN
&&
833 conn
->state
<= _OR_CONN_STATE_MAX
);
836 assert(conn
->state
>= _EXIT_CONN_STATE_MIN
&&
837 conn
->state
<= _EXIT_CONN_STATE_MAX
);
840 assert(conn
->state
>= _AP_CONN_STATE_MIN
&&
841 conn
->state
<= _AP_CONN_STATE_MAX
);
842 assert(conn
->socks_request
);
845 assert(conn
->state
>= _DIR_CONN_STATE_MIN
&&
846 conn
->state
<= _DIR_CONN_STATE_MAX
);
848 case CONN_TYPE_DNSWORKER
:
849 assert(conn
->state
== DNSWORKER_STATE_IDLE
||
850 conn
->state
== DNSWORKER_STATE_BUSY
);
852 case CONN_TYPE_CPUWORKER
:
853 assert(conn
->state
>= _CPUWORKER_STATE_MIN
&&
854 conn
->state
<= _CPUWORKER_STATE_MAX
);