connection.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #include "or.h"
  5. /********* START VARIABLES **********/
  6. extern or_options_t options; /* command-line and config-file options */
  7. extern int global_read_bucket;
  8. char *conn_type_to_string[] = {
  9. "", /* 0 */
  10. "OP listener", /* 1 */
  11. "OP", /* 2 */
  12. "OR listener", /* 3 */
  13. "OR", /* 4 */
  14. "Exit", /* 5 */
  15. "App listener",/* 6 */
  16. "App", /* 7 */
  17. "Dir listener",/* 8 */
  18. "Dir", /* 9 */
  19. "DNS worker", /* 10 */
  20. "CPU worker", /* 11 */
  21. };
  22. char *conn_state_to_string[][15] = {
  23. { NULL }, /* no type associated with 0 */
  24. { "ready" }, /* op listener, 0 */
  25. { "awaiting keys", /* op, 0 */
  26. "open", /* 1 */
  27. "close", /* 2 */
  28. "close_wait" }, /* 3 */
  29. { "ready" }, /* or listener, 0 */
  30. { "connect()ing", /* 0 */
  31. "handshaking", /* 1 */
  32. "open" }, /* 2 */
  33. { "waiting for dest info", /* exit, 0 */
  34. "connecting", /* 1 */
  35. "open" }, /* 2 */
  36. { "ready" }, /* app listener, 0 */
  37. { "", /* 0 */
  38. "", /* 1 */
  39. "", /* 2 */
  40. "awaiting dest info", /* app, 3 */
  41. "waiting for OR connection", /* 4 */
  42. "open" }, /* 5 */
  43. { "ready" }, /* dir listener, 0 */
  44. { "connecting", /* 0 */
  45. "sending command", /* 1 */
  46. "reading", /* 2 */
  47. "awaiting command", /* 3 */
  48. "writing" }, /* 4 */
  49. { "idle", /* dns worker, 0 */
  50. "busy" }, /* 1 */
  51. { "idle", /* cpu worker, 0 */
  52. "busy with onion", /* 1 */
  53. "busy with handshake" }, /* 2 */
  54. };
  55. /********* END VARIABLES ************/
  56. static int connection_init_accepted_conn(connection_t *conn);
  57. static int connection_tls_continue_handshake(connection_t *conn);
  58. static int connection_tls_finish_handshake(connection_t *conn);
  59. /**************************************************************/
  60. connection_t *connection_new(int type) {
  61. connection_t *conn;
  62. struct timeval now;
  63. my_gettimeofday(&now);
  64. conn = (connection_t *)tor_malloc(sizeof(connection_t));
  65. memset(conn,0,sizeof(connection_t)); /* zero it out to start */
  66. conn->type = type;
  67. if(buf_new(&conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen) < 0 ||
  68. buf_new(&conn->outbuf, &conn->outbuflen, &conn->outbuf_datalen) < 0)
  69. return NULL;
  70. conn->receiver_bucket = 50000; /* should be enough to do the handshake */
  71. conn->bandwidth = conn->receiver_bucket / 10; /* give it a default */
  72. conn->timestamp_created = now.tv_sec;
  73. conn->timestamp_lastread = now.tv_sec;
  74. conn->timestamp_lastwritten = now.tv_sec;
  75. return conn;
  76. }
  77. void connection_free(connection_t *conn) {
  78. assert(conn);
  79. buf_free(conn->inbuf);
  80. buf_free(conn->outbuf);
  81. if(conn->address)
  82. free(conn->address);
  83. if(connection_speaks_cells(conn)) {
  84. directory_set_dirty();
  85. if (conn->tls)
  86. tor_tls_free(conn->tls);
  87. }
  88. if (conn->pkey)
  89. crypto_free_pk_env(conn->pkey);
  90. if(conn->s > 0) {
  91. log_fn(LOG_INFO,"closing fd %d.",conn->s);
  92. close(conn->s);
  93. }
  94. free(conn);
  95. }
  96. int connection_create_listener(struct sockaddr_in *bindaddr, int type) {
  97. connection_t *conn;
  98. int s;
  99. int one=1;
  100. s = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
  101. if (s < 0) {
  102. log_fn(LOG_ERR,"Socket creation failed.");
  103. return -1;
  104. }
  105. setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&one, sizeof(one));
  106. if(bind(s,(struct sockaddr *)bindaddr,sizeof(*bindaddr)) < 0) {
  107. perror("bind ");
  108. log(LOG_ERR,"Could not bind to port %u.",ntohs(bindaddr->sin_port));
  109. return -1;
  110. }
  111. if(listen(s,SOMAXCONN) < 0) {
  112. log(LOG_ERR,"Could not listen on port %u.",ntohs(bindaddr->sin_port));
  113. return -1;
  114. }
  115. set_socket_nonblocking(s);
  116. conn = connection_new(type);
  117. if(!conn) {
  118. log_fn(LOG_DEBUG,"connection_new failed. Giving up.");
  119. return -1;
  120. }
  121. conn->s = s;
  122. if(connection_add(conn) < 0) { /* no space, forget it */
  123. log_fn(LOG_DEBUG,"connection_add failed. Giving up.");
  124. connection_free(conn);
  125. return -1;
  126. }
  127. log_fn(LOG_DEBUG,"%s listening on port %u.",conn_type_to_string[type], ntohs(bindaddr->sin_port));
  128. conn->state = LISTENER_STATE_READY;
  129. connection_start_reading(conn);
  130. return 0;
  131. }
  132. int connection_handle_listener_read(connection_t *conn, int new_type) {
  133. int news; /* the new socket */
  134. connection_t *newconn;
  135. struct sockaddr_in remote; /* information about the remote peer when connecting to other routers */
  136. int remotelen = sizeof(struct sockaddr_in); /* length of the remote address */
  137. #ifdef MS_WINDOWS
  138. int e;
  139. #endif
  140. news = accept(conn->s,(struct sockaddr *)&remote,&remotelen);
  141. if (news == -1) { /* accept() error */
  142. if(ERRNO_EAGAIN(errno)) {
  143. #ifdef MS_WINDOWS
  144. e = correct_socket_errno(conn->s);
  145. if (ERRNO_EAGAIN(e))
  146. return 0;
  147. #else
  148. return 0; /* he hung up before we could accept(). that's fine. */
  149. #endif
  150. }
  151. /* else there was a real error. */
  152. log_fn(LOG_ERR,"accept() failed. Closing.");
  153. return -1;
  154. }
  155. log(LOG_INFO,"Connection accepted on socket %d (child of fd %d).",news, conn->s);
  156. set_socket_nonblocking(news);
  157. newconn = connection_new(new_type);
  158. newconn->s = news;
  159. if(!connection_speaks_cells(newconn)) {
  160. newconn->receiver_bucket = -1;
  161. newconn->bandwidth = -1;
  162. }
  163. newconn->address = strdup(inet_ntoa(remote.sin_addr)); /* remember the remote address */
  164. newconn->addr = ntohl(remote.sin_addr.s_addr);
  165. newconn->port = ntohs(remote.sin_port);
  166. if(connection_add(newconn) < 0) { /* no space, forget it */
  167. connection_free(newconn);
  168. return 0; /* no need to tear down the parent */
  169. }
  170. if(connection_init_accepted_conn(newconn) < 0) {
  171. newconn->marked_for_close = 1;
  172. return 0;
  173. }
  174. return 0;
  175. }
  176. static int connection_init_accepted_conn(connection_t *conn) {
  177. connection_start_reading(conn);
  178. switch(conn->type) {
  179. case CONN_TYPE_OR:
  180. if(connection_tls_start_handshake(conn, 1) < 0)
  181. return -1;
  182. break;
  183. case CONN_TYPE_AP:
  184. conn->state = AP_CONN_STATE_SOCKS_WAIT;
  185. break;
  186. case CONN_TYPE_DIR:
  187. conn->state = DIR_CONN_STATE_SERVER_COMMAND_WAIT;
  188. break;
  189. }
  190. return 0;
  191. }
  192. int connection_tls_start_handshake(connection_t *conn, int receiving) {
  193. conn->state = OR_CONN_STATE_HANDSHAKING;
  194. conn->tls = tor_tls_new(conn->s, receiving);
  195. if(!conn->tls) {
  196. log_fn(LOG_ERR,"tor_tls_new failed. Closing.");
  197. return -1;
  198. }
  199. connection_start_reading(conn);
  200. log_fn(LOG_DEBUG,"starting the handshake");
  201. if(connection_tls_continue_handshake(conn) < 0)
  202. return -1;
  203. return 0;
  204. }
  205. static int connection_tls_continue_handshake(connection_t *conn) {
  206. switch(tor_tls_handshake(conn->tls)) {
  207. case TOR_TLS_ERROR:
  208. case TOR_TLS_CLOSE:
  209. log_fn(LOG_DEBUG,"tls error. breaking.");
  210. return -1;
  211. case TOR_TLS_DONE:
  212. return connection_tls_finish_handshake(conn);
  213. case TOR_TLS_WANTWRITE:
  214. connection_start_writing(conn);
  215. log_fn(LOG_DEBUG,"wanted write");
  216. return 0;
  217. case TOR_TLS_WANTREAD: /* handshaking conns are *always* reading */
  218. log_fn(LOG_DEBUG,"wanted read");
  219. return 0;
  220. }
  221. return 0;
  222. }
  223. static int connection_tls_finish_handshake(connection_t *conn) {
  224. crypto_pk_env_t *pk;
  225. routerinfo_t *router;
  226. conn->state = OR_CONN_STATE_OPEN;
  227. directory_set_dirty();
  228. connection_watch_events(conn, POLLIN);
  229. log_fn(LOG_DEBUG,"tls handshake done. verifying.");
  230. if(options.OnionRouter) { /* I'm an OR */
  231. if(tor_tls_peer_has_cert(conn->tls)) { /* it's another OR */
  232. pk = tor_tls_verify(conn->tls);
  233. if(!pk) {
  234. log_fn(LOG_INFO,"Other side has a cert but it's bad. Closing.");
  235. return -1;
  236. }
  237. router = router_get_by_pk(pk);
  238. if (!router) {
  239. log_fn(LOG_INFO,"Unrecognized public key from peer. Closing.");
  240. crypto_free_pk_env(pk);
  241. return -1;
  242. }
  243. if(conn->pkey) { /* I initiated this connection. */
  244. if(crypto_pk_cmp_keys(conn->pkey, pk)) {
  245. log_fn(LOG_INFO,"We connected to '%s' but he gave us a different key. Closing.", router->nickname);
  246. crypto_free_pk_env(pk);
  247. return -1;
  248. }
  249. log_fn(LOG_DEBUG,"The router's pk matches the one we meant to connect to. Good.");
  250. crypto_free_pk_env(pk);
  251. } else {
  252. if(connection_exact_get_by_addr_port(router->addr,router->or_port)) {
  253. log_fn(LOG_INFO,"That router is already connected. Dropping.");
  254. return -1;
  255. }
  256. conn->pkey = pk;
  257. conn->bandwidth = router->bandwidth;
  258. conn->addr = router->addr, conn->port = router->or_port;
  259. if(conn->address)
  260. free(conn->address);
  261. conn->address = strdup(router->address);
  262. }
  263. } else { /* it's an OP */
  264. conn->bandwidth = DEFAULT_BANDWIDTH_OP;
  265. }
  266. } else { /* I'm a client */
  267. if(!tor_tls_peer_has_cert(conn->tls)) { /* it's a client too?! */
  268. log_fn(LOG_INFO,"Neither peer sent a cert! Closing.");
  269. return -1;
  270. }
  271. pk = tor_tls_verify(conn->tls);
  272. if(!pk) {
  273. log_fn(LOG_INFO,"Other side has a cert but it's bad. Closing.");
  274. return -1;
  275. }
  276. router = router_get_by_pk(pk);
  277. if (!router) {
  278. log_fn(LOG_INFO,"Unrecognized public key from peer. Closing.");
  279. crypto_free_pk_env(pk);
  280. return -1;
  281. }
  282. if(crypto_pk_cmp_keys(conn->pkey, pk)) {
  283. log_fn(LOG_INFO,"We connected to '%s' but he gave us a different key. Closing.", router->nickname);
  284. crypto_free_pk_env(pk);
  285. return -1;
  286. }
  287. log_fn(LOG_DEBUG,"The router's pk matches the one we meant to connect to. Good.");
  288. crypto_free_pk_env(pk);
  289. conn->bandwidth = DEFAULT_BANDWIDTH_OP;
  290. circuit_n_conn_open(conn); /* send the pending create */
  291. }
  292. return 0;
  293. }
  294. /* take conn, make a nonblocking socket; try to connect to
  295. * addr:port (they arrive in *host order*). If fail, return -1. Else
  296. * assign s to conn->s: if connected return 1, if eagain return 0.
  297. * address is used to make the logs useful.
  298. */
  299. int connection_connect(connection_t *conn, char *address, uint32_t addr, uint16_t port) {
  300. int s;
  301. struct sockaddr_in dest_addr;
  302. s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
  303. if (s < 0) {
  304. log_fn(LOG_ERR,"Error creating network socket.");
  305. return -1;
  306. }
  307. set_socket_nonblocking(s);
  308. memset((void *)&dest_addr,0,sizeof(dest_addr));
  309. dest_addr.sin_family = AF_INET;
  310. dest_addr.sin_port = htons(port);
  311. dest_addr.sin_addr.s_addr = htonl(addr);
  312. log_fn(LOG_DEBUG,"Connecting to %s:%u.",address,port);
  313. if(connect(s,(struct sockaddr *)&dest_addr,sizeof(dest_addr)) < 0) {
  314. if(!ERRNO_CONN_EINPROGRESS(errno)) {
  315. /* yuck. kill it. */
  316. perror("connect");
  317. log_fn(LOG_DEBUG,"Connect failed.");
  318. return -1;
  319. } else {
  320. /* it's in progress. set state appropriately and return. */
  321. conn->s = s;
  322. log_fn(LOG_DEBUG,"connect in progress, socket %d.",s);
  323. return 0;
  324. }
  325. }
  326. /* it succeeded. we're connected. */
  327. log_fn(LOG_DEBUG,"Connection to %s:%u established.",address,port);
  328. conn->s = s;
  329. return 1;
  330. }
  331. /* start all connections that should be up but aren't */
  332. int retry_all_connections(uint16_t or_listenport, uint16_t ap_listenport, uint16_t dir_listenport) {
  333. struct sockaddr_in bindaddr; /* where to bind */
  334. if(or_listenport) {
  335. router_retry_connections();
  336. }
  337. memset(&bindaddr,0,sizeof(struct sockaddr_in));
  338. bindaddr.sin_family = AF_INET;
  339. bindaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* anyone can connect */
  340. if(or_listenport) {
  341. bindaddr.sin_port = htons(or_listenport);
  342. if(!connection_get_by_type(CONN_TYPE_OR_LISTENER)) {
  343. connection_create_listener(&bindaddr, CONN_TYPE_OR_LISTENER);
  344. }
  345. }
  346. if(dir_listenport) {
  347. bindaddr.sin_port = htons(dir_listenport);
  348. if(!connection_get_by_type(CONN_TYPE_DIR_LISTENER)) {
  349. connection_create_listener(&bindaddr, CONN_TYPE_DIR_LISTENER);
  350. }
  351. }
  352. if(ap_listenport) {
  353. bindaddr.sin_port = htons(ap_listenport);
  354. bindaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* the AP listens only on localhost! */
  355. if(!connection_get_by_type(CONN_TYPE_AP_LISTENER)) {
  356. connection_create_listener(&bindaddr, CONN_TYPE_AP_LISTENER);
  357. }
  358. }
  359. return 0;
  360. }
  361. int connection_handle_read(connection_t *conn) {
  362. struct timeval now;
  363. my_gettimeofday(&now);
  364. conn->timestamp_lastread = now.tv_sec;
  365. switch(conn->type) {
  366. case CONN_TYPE_OR_LISTENER:
  367. return connection_handle_listener_read(conn, CONN_TYPE_OR);
  368. case CONN_TYPE_AP_LISTENER:
  369. return connection_handle_listener_read(conn, CONN_TYPE_AP);
  370. case CONN_TYPE_DIR_LISTENER:
  371. return connection_handle_listener_read(conn, CONN_TYPE_DIR);
  372. }
  373. if(connection_read_to_buf(conn) < 0) {
  374. if(conn->type == CONN_TYPE_DIR &&
  375. (conn->state == DIR_CONN_STATE_CONNECTING_GET || DIR_CONN_STATE_CONNECTING_POST)) {
  376. /* it's a directory server and connecting failed: forget about this router */
  377. /* XXX I suspect pollerr may make Windows not get to this point. :( */
  378. router_forget_router(conn->addr,conn->port);
  379. /* FIXME i don't think router_forget_router works. */
  380. }
  381. return -1;
  382. }
  383. if(connection_process_inbuf(conn) < 0) {
  384. //log_fn(LOG_DEBUG,"connection_process_inbuf returned %d.",retval);
  385. return -1;
  386. }
  387. if(!connection_state_is_open(conn) && conn->receiver_bucket == 0) {
  388. log_fn(LOG_DEBUG,"receiver bucket reached 0 before handshake finished. Closing.");
  389. return -1;
  390. }
  391. return 0;
  392. }
  393. /* return -1 if we want to break conn, else return 0 */
  394. int connection_read_to_buf(connection_t *conn) {
  395. int result;
  396. int at_most;
  397. assert((connection_speaks_cells(conn) && conn->receiver_bucket >= 0) ||
  398. (!connection_speaks_cells(conn) && conn->receiver_bucket < 0));
  399. if(options.LinkPadding) {
  400. at_most = global_read_bucket;
  401. } else {
  402. /* do a rudimentary round-robin so one connection can't hog a thickpipe */
  403. if(connection_speaks_cells(conn)) {
  404. at_most = 10*(CELL_NETWORK_SIZE);
  405. } else {
  406. at_most = 10*(CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE);
  407. }
  408. if(at_most > global_read_bucket)
  409. at_most = global_read_bucket;
  410. }
  411. if(conn->receiver_bucket >= 0 && at_most > conn->receiver_bucket)
  412. at_most = conn->receiver_bucket;
  413. if(connection_speaks_cells(conn) && conn->state != OR_CONN_STATE_CONNECTING) {
  414. if(conn->state == OR_CONN_STATE_HANDSHAKING)
  415. return connection_tls_continue_handshake(conn);
  416. /* else open, or closing */
  417. result = read_to_buf_tls(conn->tls, at_most, &conn->inbuf,
  418. &conn->inbuflen, &conn->inbuf_datalen);
  419. switch(result) {
  420. case TOR_TLS_ERROR:
  421. case TOR_TLS_CLOSE:
  422. log_fn(LOG_DEBUG,"tls error. breaking.");
  423. return -1; /* XXX deal with close better */
  424. case TOR_TLS_WANTWRITE:
  425. connection_start_writing(conn);
  426. return 0;
  427. case TOR_TLS_WANTREAD: /* we're already reading */
  428. case TOR_TLS_DONE: /* no data read, so nothing to process */
  429. return 0;
  430. }
  431. } else {
  432. result = read_to_buf(conn->s, at_most, &conn->inbuf, &conn->inbuflen,
  433. &conn->inbuf_datalen, &conn->inbuf_reached_eof);
  434. // log(LOG_DEBUG,"connection_read_to_buf(): read_to_buf returned %d.",read_result);
  435. if(result < 0)
  436. return -1;
  437. }
  438. global_read_bucket -= result; assert(global_read_bucket >= 0);
  439. if(connection_speaks_cells(conn))
  440. conn->receiver_bucket -= result;
  441. if(conn->receiver_bucket == 0 || global_read_bucket == 0) {
  442. log_fn(LOG_DEBUG,"buckets (%d, %d) exhausted. Pausing.", global_read_bucket, conn->receiver_bucket);
  443. conn->wants_to_read = 1;
  444. connection_stop_reading(conn);
  445. }
  446. return 0;
  447. }
  448. int connection_fetch_from_buf(char *string, int len, connection_t *conn) {
  449. return fetch_from_buf(string, len, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen);
  450. }
  451. int connection_find_on_inbuf(char *string, int len, connection_t *conn) {
  452. return find_on_inbuf(string, len, conn->inbuf, conn->inbuf_datalen);
  453. }
  454. int connection_wants_to_flush(connection_t *conn) {
  455. return conn->outbuf_flushlen;
  456. }
  457. int connection_outbuf_too_full(connection_t *conn) {
  458. return (conn->outbuf_flushlen > 10*CELL_PAYLOAD_SIZE);
  459. }
  460. int connection_flush_buf(connection_t *conn) {
  461. return flush_buf(conn->s, &conn->outbuf, &conn->outbuflen,
  462. &conn->outbuf_flushlen, &conn->outbuf_datalen);
  463. }
  464. /* return -1 if you want to break the conn, else return 0 */
  465. int connection_handle_write(connection_t *conn) {
  466. struct timeval now;
  467. if(connection_is_listener(conn)) {
  468. log_fn(LOG_DEBUG,"Got a listener socket. Can't happen!");
  469. return -1;
  470. }
  471. my_gettimeofday(&now);
  472. conn->timestamp_lastwritten = now.tv_sec;
  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);
  477. }
  478. /* else open, or closing */
  479. switch(flush_buf_tls(conn->tls, &conn->outbuf, &conn->outbuflen,
  480. &conn->outbuf_flushlen, &conn->outbuf_datalen)) {
  481. case TOR_TLS_ERROR:
  482. case TOR_TLS_CLOSE:
  483. log_fn(LOG_DEBUG,"tls error. breaking.");
  484. return -1; /* XXX deal with close better */
  485. case TOR_TLS_WANTWRITE:
  486. /* we're already writing */
  487. return 0;
  488. case TOR_TLS_WANTREAD:
  489. /* Make sure to avoid a loop if the receive buckets are empty. */
  490. if(!connection_is_reading(conn)) {
  491. connection_stop_writing(conn);
  492. conn->wants_to_write = 1;
  493. /* we'll start reading again when the next second arrives,
  494. * and then also start writing again.
  495. */
  496. }
  497. /* else no problem, we're already reading */
  498. return 0;
  499. /* case TOR_TLS_DONE:
  500. * for TOR_TLS_DONE, fall through to check if the flushlen
  501. * is empty, so we can stop writing.
  502. */
  503. }
  504. } else {
  505. if(flush_buf(conn->s, &conn->outbuf, &conn->outbuflen,
  506. &conn->outbuf_flushlen, &conn->outbuf_datalen) < 0)
  507. return -1;
  508. /* conns in CONNECTING state will fall through... */
  509. }
  510. if(!connection_wants_to_flush(conn)) /* it's done flushing */
  511. if(connection_finished_flushing(conn) < 0) /* ...and get handled here. */
  512. return -1;
  513. return 0;
  514. }
  515. int connection_write_to_buf(char *string, int len, connection_t *conn) {
  516. if(!len)
  517. return 0;
  518. if(conn->marked_for_close)
  519. return 0;
  520. if( (!connection_speaks_cells(conn)) ||
  521. (!connection_state_is_open(conn)) ||
  522. (options.LinkPadding == 0) ) {
  523. /* connection types other than or, or or not in 'open' state, should flush immediately */
  524. /* also flush immediately if we're not doing LinkPadding, since otherwise it will never flush */
  525. connection_start_writing(conn);
  526. conn->outbuf_flushlen += len;
  527. }
  528. return write_to_buf(string, len, &conn->outbuf, &conn->outbuflen, &conn->outbuf_datalen);
  529. }
  530. int connection_receiver_bucket_should_increase(connection_t *conn) {
  531. assert(conn);
  532. if(!connection_speaks_cells(conn))
  533. return 0; /* edge connections don't use receiver_buckets */
  534. if(conn->receiver_bucket > 9*conn->bandwidth)
  535. return 0;
  536. return 1;
  537. }
  538. int connection_is_listener(connection_t *conn) {
  539. if(conn->type == CONN_TYPE_OR_LISTENER ||
  540. conn->type == CONN_TYPE_AP_LISTENER ||
  541. conn->type == CONN_TYPE_DIR_LISTENER)
  542. return 1;
  543. return 0;
  544. }
  545. int connection_state_is_open(connection_t *conn) {
  546. assert(conn);
  547. if((conn->type == CONN_TYPE_OR && conn->state == OR_CONN_STATE_OPEN) ||
  548. (conn->type == CONN_TYPE_AP && conn->state == AP_CONN_STATE_OPEN) ||
  549. (conn->type == CONN_TYPE_EXIT && conn->state == EXIT_CONN_STATE_OPEN))
  550. return 1;
  551. return 0;
  552. }
  553. int connection_send_destroy(aci_t aci, connection_t *conn) {
  554. cell_t cell;
  555. assert(conn);
  556. if(!connection_speaks_cells(conn)) {
  557. log_fn(LOG_INFO,"Aci %d: At an edge. Marking connection for close.", aci);
  558. conn->marked_for_close = 1;
  559. return 0;
  560. }
  561. memset(&cell, 0, sizeof(cell_t));
  562. cell.aci = aci;
  563. cell.command = CELL_DESTROY;
  564. log_fn(LOG_INFO,"Sending destroy (aci %d).",aci);
  565. return connection_write_cell_to_buf(&cell, conn);
  566. }
  567. int connection_process_inbuf(connection_t *conn) {
  568. assert(conn);
  569. switch(conn->type) {
  570. case CONN_TYPE_OR:
  571. return connection_or_process_inbuf(conn);
  572. case CONN_TYPE_EXIT:
  573. case CONN_TYPE_AP:
  574. return connection_edge_process_inbuf(conn);
  575. case CONN_TYPE_DIR:
  576. return connection_dir_process_inbuf(conn);
  577. case CONN_TYPE_DNSWORKER:
  578. return connection_dns_process_inbuf(conn);
  579. case CONN_TYPE_CPUWORKER:
  580. return connection_cpu_process_inbuf(conn);
  581. default:
  582. log_fn(LOG_DEBUG,"got unexpected conn->type.");
  583. return -1;
  584. }
  585. }
  586. int connection_finished_flushing(connection_t *conn) {
  587. assert(conn);
  588. // log_fn(LOG_DEBUG,"entered. Socket %u.", conn->s);
  589. switch(conn->type) {
  590. case CONN_TYPE_OR:
  591. return connection_or_finished_flushing(conn);
  592. case CONN_TYPE_AP:
  593. case CONN_TYPE_EXIT:
  594. return connection_edge_finished_flushing(conn);
  595. case CONN_TYPE_DIR:
  596. return connection_dir_finished_flushing(conn);
  597. case CONN_TYPE_DNSWORKER:
  598. return connection_dns_finished_flushing(conn);
  599. case CONN_TYPE_CPUWORKER:
  600. return connection_cpu_finished_flushing(conn);
  601. default:
  602. log_fn(LOG_DEBUG,"got unexpected conn->type.");
  603. return -1;
  604. }
  605. }
  606. void assert_connection_ok(connection_t *conn, time_t now)
  607. {
  608. assert(conn);
  609. assert(conn->type >= _CONN_TYPE_MIN);
  610. assert(conn->type <= _CONN_TYPE_MAX);
  611. /* XXX check: wants_to_read, wants_to_write, s, poll_index,
  612. * marked_for_close. */
  613. /* buffers */
  614. assert(conn->inbuf);
  615. assert(conn->inbuflen <= conn->inbuf_datalen);
  616. assert(conn->inbuflen >= 0);
  617. assert(conn->inbuf_datalen > 0);
  618. assert(conn->outbuf);
  619. assert(conn->outbuflen <= conn->outbuf_datalen);
  620. assert(conn->outbuflen >= 0);
  621. assert(conn->outbuf_datalen > 0);
  622. assert(!now || conn->timestamp_lastread <= now);
  623. assert(!now || conn->timestamp_lastwritten <= now);
  624. assert(conn->timestamp_created <= conn->timestamp_lastread);
  625. assert(conn->timestamp_created <= conn->timestamp_lastwritten);
  626. if (conn->type != CONN_TYPE_OR) {
  627. assert(conn->bandwidth == -1);
  628. assert(conn->receiver_bucket == -1);
  629. /* Addr, port, address XXX */
  630. assert(!conn->pkey);
  631. assert(!conn->tls);
  632. } else {
  633. assert(conn->bandwidth);
  634. assert(conn->receiver_bucket >= 0);
  635. assert(conn->receiver_bucket <= 10*conn->bandwidth);
  636. assert(conn->addr && conn->port);
  637. assert(conn->address);
  638. assert(conn->pkey);
  639. if (conn->state != OR_CONN_STATE_CONNECTING)
  640. assert(conn->tls);
  641. }
  642. if (conn->type != CONN_TYPE_EXIT && conn->type != CONN_TYPE_AP) {
  643. assert(!conn->stream_id[0]);
  644. assert(!conn->next_stream);
  645. assert(!conn->cpath_layer);
  646. assert(!conn->package_window);
  647. assert(!conn->deliver_window);
  648. assert(!conn->done_sending);
  649. assert(!conn->done_receiving);
  650. } else {
  651. assert(!conn->next_stream ||
  652. conn->next_stream->type == CONN_TYPE_EXIT ||
  653. conn->next_stream->type == CONN_TYPE_AP);
  654. assert(conn->cpath_layer);
  655. assert_cpath_layer_ok(conn->cpath_layer);
  656. /* XXX unchecked, package window, deliver window. */
  657. }
  658. switch(conn->type)
  659. {
  660. case CONN_TYPE_OR_LISTENER:
  661. case CONN_TYPE_AP_LISTENER:
  662. case CONN_TYPE_DIR_LISTENER:
  663. assert(conn->state == LISTENER_STATE_READY);
  664. break;
  665. case CONN_TYPE_OR:
  666. assert(conn->state >= _OR_CONN_STATE_MIN &&
  667. conn->state <= _OR_CONN_STATE_MAX);
  668. break;
  669. case CONN_TYPE_EXIT:
  670. assert(conn->state >= _EXIT_CONN_STATE_MIN &&
  671. conn->state <= _EXIT_CONN_STATE_MAX);
  672. break;
  673. case CONN_TYPE_AP:
  674. assert(conn->state >= _AP_CONN_STATE_MIN &&
  675. conn->state <= _AP_CONN_STATE_MAX);
  676. break;
  677. case CONN_TYPE_DIR:
  678. assert(conn->state >= _DIR_CONN_STATE_MIN &&
  679. conn->state <= _DIR_CONN_STATE_MAX);
  680. break;
  681. case CONN_TYPE_DNSWORKER:
  682. assert(conn->state == DNSWORKER_STATE_IDLE ||
  683. conn->state == DNSWORKER_STATE_BUSY);
  684. case CONN_TYPE_CPUWORKER:
  685. assert(conn->state >= _CPUWORKER_STATE_MIN &&
  686. conn->state <= _CPUWORKER_STATE_MAX);
  687. break;
  688. default:
  689. assert(0);
  690. }
  691. }
  692. /*
  693. Local Variables:
  694. mode:c
  695. indent-tabs-mode:nil
  696. c-basic-offset:2
  697. End:
  698. */