|
@@ -31,13 +31,50 @@ void command_process_cell(cell_t *cell, connection_t *conn) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/* helper function for command_process_create_cell */
|
|
|
+static int deliver_onion_to_conn(aci_t aci, unsigned char *onion, uint32_t onionlen, connection_t *conn) {
|
|
|
+ char *buf;
|
|
|
+ int buflen, dataleft;
|
|
|
+ cell_t cell;
|
|
|
+
|
|
|
+ assert(aci && onion && onionlen);
|
|
|
+
|
|
|
+ buflen = onionlen+4;
|
|
|
+ buf = malloc(buflen);
|
|
|
+ if(!buf)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ log(LOG_DEBUG,"deliver_onion_to_conn(): Setting onion length to %u.",onionlen);
|
|
|
+ *(uint32_t*)buf = htonl(onionlen);
|
|
|
+ memcpy((void *)(buf+4),(void *)onion,onionlen);
|
|
|
+
|
|
|
+ dataleft = buflen;
|
|
|
+ while(dataleft > 0) {
|
|
|
+ memset(&cell,0,sizeof(cell_t));
|
|
|
+ cell.command = CELL_CREATE;
|
|
|
+ cell.aci = aci;
|
|
|
+ if(dataleft >= CELL_PAYLOAD_SIZE)
|
|
|
+ cell.length = CELL_PAYLOAD_SIZE;
|
|
|
+ else
|
|
|
+ cell.length = dataleft;
|
|
|
+ memcpy(cell.payload, buf+buflen-dataleft, cell.length);
|
|
|
+ dataleft -= cell.length;
|
|
|
+
|
|
|
+ log(LOG_DEBUG,"deliver_onion_to_conn(): Delivering create cell, payload %d bytes.",cell.length);
|
|
|
+ if(connection_write_cell_to_buf(&cell, conn) < 0) {
|
|
|
+ log(LOG_DEBUG,"deliver_onion_to_conn(): Could not buffer new create cells. Closing.");
|
|
|
+ free(buf);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ free(buf);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
void command_process_create_cell(cell_t *cell, connection_t *conn) {
|
|
|
circuit_t *circ;
|
|
|
connection_t *n_conn;
|
|
|
- unsigned char *cellbuf; /* array of cells */
|
|
|
- int cellbuflen; /* size of cellbuf in bytes */
|
|
|
- cell_t *tmpcell; /* pointer to an arbitrary cell */
|
|
|
- int retval, i;
|
|
|
+ int retval;
|
|
|
|
|
|
circ = circuit_get_by_aci_conn(cell->aci, conn);
|
|
|
|
|
@@ -122,30 +159,14 @@ void command_process_create_cell(cell_t *cell, connection_t *conn) {
|
|
|
pad_onion(circ->onion,circ->onionlen, sizeof(onion_layer_t));
|
|
|
log(LOG_DEBUG,"command_process_create_cell(): Padded the onion with random data.");
|
|
|
|
|
|
- retval = pack_create(circ->n_aci, circ->onion, circ->onionlen, &cellbuf, &cellbuflen);
|
|
|
+ retval = deliver_onion_to_conn(circ->n_aci, circ->onion, circ->onionlen, n_conn);
|
|
|
+// retval = pack_create(circ->n_aci, circ->onion, circ->onionlen, &cellbuf, &cellbuflen);
|
|
|
free((void *)circ->onion);
|
|
|
circ->onion = NULL;
|
|
|
- if (retval == -1) /* pack_create() error */
|
|
|
- {
|
|
|
- log(LOG_DEBUG,"command_process_create_cell(): Could not pack the onion into CREATE cells. Closing the connection.");
|
|
|
+ if (retval == -1) {
|
|
|
+ log(LOG_DEBUG,"command_process_create_cell(): Could not deliver the onion to next conn. Closing.");
|
|
|
circuit_close(circ);
|
|
|
- return;
|
|
|
- }
|
|
|
- log(LOG_DEBUG,"command_process_create_cell(): Onion packed into CREATE cells. Buffering the cells.");
|
|
|
- /* queue the create cells for transmission to the next hop */
|
|
|
- tmpcell = (cell_t *)cellbuf;
|
|
|
- for (i=0;i<cellbuflen/sizeof(cell_t);i++)
|
|
|
- {
|
|
|
- retval = connection_write_cell_to_buf(tmpcell, n_conn);
|
|
|
- if (retval == -1) /* buffering failed, drop the connection */
|
|
|
- {
|
|
|
- log(LOG_DEBUG,"command_process_create_cell(): Could not buffer new create cells. Closing.");
|
|
|
- circuit_close(circ);
|
|
|
- return;
|
|
|
- }
|
|
|
- tmpcell++;
|
|
|
}
|
|
|
- free((void *)cellbuf);
|
|
|
return;
|
|
|
|
|
|
} else { /* this is destined for an exit */
|