aboutsummaryrefslogtreecommitdiff
path: root/src/or/connection.c
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2002-07-02 09:36:58 +0000
committerRoger Dingledine <arma@torproject.org>2002-07-02 09:36:58 +0000
commitd982925593dbb724e4c8ebeb4f945c2184f11831 (patch)
treec3f22938ad261f3c45ed2744ae0950388c1c04e8 /src/or/connection.c
parentb34fad4d38ac9c45eb2112fa9dde26e499ccdcc5 (diff)
downloadtor-d982925593dbb724e4c8ebeb4f945c2184f11831.tar
tor-d982925593dbb724e4c8ebeb4f945c2184f11831.tar.gz
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what roles this server should play -- connect to all ORs, listen for ORs, listen for OPs, listen for APs, or any combination. * everything in /src/op/ is now obsolete. * connection_ap.c now handles all interactions with application proxies * "port" is now or_port, op_port, ap_port. But routers are still always referenced (say, in conn_get_by_addr_port()) by addr / or_port. We should make routers.c actually read these new ports (currently I've kludged it so op_port = or_port+10, ap_port=or_port+20) * circuits currently know if they're at the beginning of the path because circ->cpath is set. They use this instead for crypts (both ways), if it's set. * I still obey the "send a 0 back to the AP when you're ready" protocol, but I think we should phase it out. I can simply not read from the AP socket until I'm ready. I need to do a lot of cleanup work here, but the code appears to work, so now's a good time for a checkin. svn:r22
Diffstat (limited to 'src/or/connection.c')
-rw-r--r--src/or/connection.c140
1 files changed, 116 insertions, 24 deletions
diff --git a/src/or/connection.c b/src/or/connection.c
index 643b1ebb8..b44d72c68 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -61,6 +61,10 @@ void connection_free(connection_t *conn) {
buf_free(conn->outbuf);
if(conn->address)
free(conn->address);
+ if(conn->dest_addr)
+ free(conn->dest_addr);
+ if(conn->dest_port)
+ free(conn->dest_port);
/* FIXME should we do these for all connections, or just ORs, or what */
if(conn->type == CONN_TYPE_OR ||
@@ -161,18 +165,11 @@ int connection_handle_listener_read(connection_t *conn, int new_type, int new_st
return 0;
}
-int retry_all_connections(routerinfo_t **router_array, int rarray_len,
- RSA *prkey, uint16_t or_port, uint16_t op_port, uint16_t ap_port) {
-
- /* start all connections that should be up but aren't */
-
- routerinfo_t *router;
- int i;
-
+/* private function, to create the 'local' variable used below */
+static int learn_local(struct sockaddr_in *local) {
/* local host information */
char localhostname[512];
struct hostent *localhost;
- struct sockaddr_in local; /* local address */
/* obtain local host information */
if(gethostname(localhostname,512) < 0) {
@@ -184,31 +181,69 @@ int retry_all_connections(routerinfo_t **router_array, int rarray_len,
log(LOG_ERR,"Error obtaining local host info.");
return -1;
}
- memset((void *)&local,0,sizeof(local));
- local.sin_family = AF_INET;
- local.sin_addr.s_addr = INADDR_ANY;
- local.sin_port = htons(or_port);
- memcpy((void *)&local.sin_addr,(void *)localhost->h_addr,sizeof(struct in_addr));
-
- for (i=0;i<rarray_len;i++) {
- router = router_array[i];
- if(!connection_get_by_addr_port(router->addr,router->port)) { /* not in the list */
- connect_to_router(router, prkey, &local);
+ memset((void *)local,0,sizeof(struct sockaddr_in));
+ local->sin_family = AF_INET;
+ local->sin_addr.s_addr = INADDR_ANY;
+ memcpy((void *)&local->sin_addr,(void *)localhost->h_addr,sizeof(struct in_addr));
+
+ return 0;
+}
+
+int retry_all_connections(int role, routerinfo_t **router_array, int rarray_len,
+ RSA *prkey, uint16_t or_listenport, uint16_t op_listenport, uint16_t ap_listenport) {
+
+ /* start all connections that should be up but aren't */
+
+ routerinfo_t *router;
+ int i;
+ struct sockaddr_in local; /* local address */
+
+ if(learn_local(&local) < 0)
+ return -1;
+
+ local.sin_port = htons(or_listenport);
+ if(role & ROLE_OR_CONNECT_ALL) {
+ for (i=0;i<rarray_len;i++) {
+ router = router_array[i];
+ if(!connection_get_by_addr_port(router->addr,router->or_port)) { /* not in the list */
+ log(LOG_DEBUG,"retry_all_connections(): connecting to OR %s:%u.",router->address,ntohs(router->or_port));
+ connection_or_connect_as_or(router, prkey, &local);
+ }
}
}
- if(!connection_get_by_type(CONN_TYPE_OR_LISTENER)) {
- connection_or_create_listener(prkey, &local);
+ if(role & ROLE_OR_LISTEN) {
+ if(!connection_get_by_type(CONN_TYPE_OR_LISTENER)) {
+ connection_or_create_listener(prkey, &local);
+ }
}
- local.sin_port = htons(op_port);
- if(!connection_get_by_type(CONN_TYPE_OP_LISTENER)) {
- connection_op_create_listener(prkey, &local);
+ if(role & ROLE_OP_LISTEN) {
+ local.sin_port = htons(op_listenport);
+ if(!connection_get_by_type(CONN_TYPE_OP_LISTENER)) {
+ connection_op_create_listener(prkey, &local);
+ }
+ }
+
+ if(role & ROLE_AP_LISTEN) {
+ local.sin_port = htons(ap_listenport);
+ if(!connection_get_by_type(CONN_TYPE_AP_LISTENER)) {
+ connection_ap_create_listener(NULL, &local); /* no need to tell it the private key. */
+ }
}
return 0;
}
+connection_t *connection_connect_to_router_as_op(routerinfo_t *router, RSA *prkey, uint16_t local_or_port) {
+ struct sockaddr_in local; /* local address */
+
+ if(learn_local(&local) < 0)
+ return NULL;
+ local.sin_port = htons(local_or_port);
+ return connection_or_connect_as_or(router, prkey, &local);
+}
+
int connection_read_to_buf(connection_t *conn) {
return read_to_buf(conn->s, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen, &conn->inbuf_reached_eof);
}
@@ -234,6 +269,7 @@ int connection_send_destroy(aci_t aci, connection_t *conn) {
assert(conn);
if(conn->type == CONN_TYPE_OP ||
+ conn->type == CONN_TYPE_AP ||
conn->type == CONN_TYPE_EXIT) {
log(LOG_DEBUG,"connection_send_destroy(): At an edge. Marking connection for close.");
conn->marked_for_close = 1;
@@ -296,12 +332,66 @@ int connection_process_inbuf(connection_t *conn) {
return connection_or_process_inbuf(conn);
case CONN_TYPE_EXIT:
return connection_exit_process_inbuf(conn);
+ case CONN_TYPE_AP:
+ return connection_ap_process_inbuf(conn);
default:
log(LOG_DEBUG,"connection_process_inbuf() got unexpected conn->type.");
return -1;
}
}
+int connection_package_raw_inbuf(connection_t *conn) {
+ int amount_to_process;
+ cell_t cell;
+ circuit_t *circ;
+
+ assert(conn);
+ assert(conn->type == CONN_TYPE_EXIT || conn->type == CONN_TYPE_AP);
+
+ amount_to_process = conn->inbuf_datalen;
+
+ if(!amount_to_process)
+ return 0;
+
+ if(amount_to_process > CELL_PAYLOAD_SIZE) {
+ cell.length = CELL_PAYLOAD_SIZE;
+ } else {
+ cell.length = amount_to_process;
+ }
+
+ if(connection_fetch_from_buf(cell.payload, cell.length, conn) < 0)
+ return -1;
+
+ circ = circuit_get_by_conn(conn);
+ if(!circ) {
+ log(LOG_DEBUG,"connection_raw_package_inbuf(): conn has no circuits!");
+ return -1;
+ }
+
+ log(LOG_DEBUG,"connection_raw_package_inbuf(): Packaging %d bytes.",cell.length);
+ if(circ->n_conn == conn) { /* send it backward. we're an exit. */
+ cell.aci = circ->p_aci;
+ cell.command = CELL_DATA;
+ if(circuit_deliver_data_cell(&cell, circ, circ->p_conn, 'e') < 0) {
+ log(LOG_DEBUG,"connection_raw_package_inbuf(): circuit_deliver_data_cell (backward) failed. Closing.");
+ circuit_close(circ);
+ return 0;
+ }
+ } else { /* send it forward. we're an AP */
+ cell.aci = circ->n_aci;
+ cell.command = CELL_DATA;
+ if(circuit_deliver_data_cell(&cell, circ, circ->n_conn, 'e') < 0) {
+ /* yes, we use 'e' here, because the AP connection must *encrypt* its input. */
+ log(LOG_DEBUG,"connection_raw_package_inbuf(): circuit_deliver_data_cell (forward) failed. Closing.");
+ circuit_close(circ);
+ return 0;
+ }
+ }
+ if(amount_to_process > CELL_PAYLOAD_SIZE)
+ return connection_package_raw_inbuf(conn);
+ return 0;
+}
+
int connection_finished_flushing(connection_t *conn) {
assert(conn);
@@ -309,6 +399,8 @@ int connection_finished_flushing(connection_t *conn) {
log(LOG_DEBUG,"connection_finished_flushing() entered. Socket %u.", conn->s);
switch(conn->type) {
+ case CONN_TYPE_AP:
+ return connection_ap_finished_flushing(conn);
case CONN_TYPE_OP:
return connection_op_finished_flushing(conn);
case CONN_TYPE_OR: