|
@@ -126,6 +126,29 @@ connection_t *connection_new(int type) {
|
|
if(type == CONN_TYPE_OR) {
|
|
if(type == CONN_TYPE_OR) {
|
|
directory_set_dirty();
|
|
directory_set_dirty();
|
|
}
|
|
}
|
|
|
|
+#ifdef USE_ZLIB
|
|
|
|
+ if (type == CONN_TYPE_AP || type == CONN_TYPE_EXIT) {
|
|
|
|
+ if (buf_new(&conn->z_outbuf, &conn->z_outbuflen, &conn->z_outbuf_datalen) < 0)
|
|
|
|
+ return NULL;
|
|
|
|
+ if (! (conn->compression = malloc(sizeof(z_stream))))
|
|
|
|
+ return NULL;
|
|
|
|
+ if (! (conn->decompression = malloc(sizeof(z_stream))))
|
|
|
|
+ return NULL;
|
|
|
|
+ memset(conn->compression, 0, sizeof(z_stream));
|
|
|
|
+ memset(conn->decompression, 0, sizeof(z_stream));
|
|
|
|
+ if (deflateInit(conn->compression, Z_DEFAULT_COMPRESSION) != Z_OK) {
|
|
|
|
+ log(LOG_ERR, "Error initializing zlib: %s", conn->compression->msg);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ if (inflateInit(conn->decompression) != Z_OK) {
|
|
|
|
+ log(LOG_ERR, "Error initializing zlib: %s", conn->decompression->msg);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ conn->compression = conn->decompression = NULL;
|
|
|
|
+ }
|
|
|
|
+ conn->done_sending = conn->done_receiving = 0
|
|
|
|
+#endif
|
|
return conn;
|
|
return conn;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -156,6 +179,19 @@ void connection_free(connection_t *conn) {
|
|
if(conn->type == CONN_TYPE_OR) {
|
|
if(conn->type == CONN_TYPE_OR) {
|
|
directory_set_dirty();
|
|
directory_set_dirty();
|
|
}
|
|
}
|
|
|
|
+#ifdef USE_ZLIB
|
|
|
|
+ if (conn->compression) {
|
|
|
|
+ if (inflateEnd(conn->decompression) != Z_OK)
|
|
|
|
+ log(LOG_ERR,"connection_free(): while closing zlib: %s",
|
|
|
|
+ conn->decompression->msg);
|
|
|
|
+ if (deflateEnd(conn->compression) != Z_OK)
|
|
|
|
+ log(LOG_ERR,"connection_free(): while closing zlib: %s",
|
|
|
|
+ conn->compression->msg);
|
|
|
|
+ free(conn->compression);
|
|
|
|
+ free(conn->decompression);
|
|
|
|
+ buf_free(conn->z_outbuf);
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
free(conn);
|
|
free(conn);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -337,6 +373,49 @@ int connection_fetch_from_buf(char *string, int len, connection_t *conn) {
|
|
return fetch_from_buf(string, len, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen);
|
|
return fetch_from_buf(string, len, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef USE_ZLIB
|
|
|
|
+int connection_compress_from_buf(char *string, int len, connection_t *conn,
|
|
|
|
+ int flush) {
|
|
|
|
+ return compress_from_buf(string, len,
|
|
|
|
+ &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen,
|
|
|
|
+ conn->compression, flush);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int connection_decompress_to_buf(char *string, int len, connection_t *conn,
|
|
|
|
+ int flush) {
|
|
|
|
+ /* This is not sane with respect to flow control; we want to spool out to
|
|
|
|
+ * z_outbuf, but only decompress and write as needed.
|
|
|
|
+ */
|
|
|
|
+ int n;
|
|
|
|
+ struct timeval now;
|
|
|
|
+
|
|
|
|
+ if (write_to_buf(string, len,
|
|
|
|
+ &conn->z_outbuf, &conn->z_outbuflen, &conn->z_outbuf_datalen) < 0)
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ n = decompress_buf_to_buf(
|
|
|
|
+ &conn->z_outbuf, &conn->z_outbuflen, &conn->z_outbuf_datalen,
|
|
|
|
+ &conn->outbuf, &conn->outbuflen, &conn->outbuf_datalen,
|
|
|
|
+ conn->decompression, flush);
|
|
|
|
+
|
|
|
|
+ if (n < 0)
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ if(gettimeofday(&now,NULL) < 0)
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ if(!n)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ if(conn->marked_for_close)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ conn->timestamp_lastwritten = now.tv_sec;
|
|
|
|
+
|
|
|
|
+ return n;
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
+
|
|
int connection_find_on_inbuf(char *string, int len, connection_t *conn) {
|
|
int connection_find_on_inbuf(char *string, int len, connection_t *conn) {
|
|
return find_on_inbuf(string, len, conn->inbuf, conn->inbuf_datalen);
|
|
return find_on_inbuf(string, len, conn->inbuf, conn->inbuf_datalen);
|
|
}
|
|
}
|
|
@@ -607,7 +686,7 @@ int connection_process_inbuf(connection_t *conn) {
|
|
}
|
|
}
|
|
|
|
|
|
int connection_package_raw_inbuf(connection_t *conn) {
|
|
int connection_package_raw_inbuf(connection_t *conn) {
|
|
- int amount_to_process;
|
|
|
|
|
|
+ int amount_to_process, len;
|
|
cell_t cell;
|
|
cell_t cell;
|
|
circuit_t *circ;
|
|
circuit_t *circ;
|
|
|
|
|
|
@@ -618,13 +697,27 @@ int connection_package_raw_inbuf(connection_t *conn) {
|
|
repeat_connection_package_raw_inbuf:
|
|
repeat_connection_package_raw_inbuf:
|
|
|
|
|
|
amount_to_process = conn->inbuf_datalen;
|
|
amount_to_process = conn->inbuf_datalen;
|
|
-
|
|
|
|
|
|
+
|
|
if(!amount_to_process)
|
|
if(!amount_to_process)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
/* Initialize the cell with 0's */
|
|
/* Initialize the cell with 0's */
|
|
memset(&cell, 0, sizeof(cell_t));
|
|
memset(&cell, 0, sizeof(cell_t));
|
|
|
|
|
|
|
|
+#ifdef USE_ZLIB
|
|
|
|
+ /* This compression logic is not necessarily optimal:
|
|
|
|
+ * 1) Maybe we should try to read as much as we can onto the inbuf before
|
|
|
|
+ * compressing.
|
|
|
|
+ * 2)
|
|
|
|
+ */
|
|
|
|
+ len = connection_compress_from_buf(cell.payload + TOPIC_HEADER_SIZE,
|
|
|
|
+ CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE,
|
|
|
|
+ conn, Z_SYNC_FLUSH);
|
|
|
|
+ if (len < 0)
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ cell.length = len;
|
|
|
|
+#else
|
|
if(amount_to_process > CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE) {
|
|
if(amount_to_process > CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE) {
|
|
cell.length = CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE;
|
|
cell.length = CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE;
|
|
} else {
|
|
} else {
|
|
@@ -633,6 +726,7 @@ repeat_connection_package_raw_inbuf:
|
|
|
|
|
|
if(connection_fetch_from_buf(cell.payload+TOPIC_HEADER_SIZE, cell.length, conn) < 0)
|
|
if(connection_fetch_from_buf(cell.payload+TOPIC_HEADER_SIZE, cell.length, conn) < 0)
|
|
return -1;
|
|
return -1;
|
|
|
|
+#endif
|
|
|
|
|
|
circ = circuit_get_by_conn(conn);
|
|
circ = circuit_get_by_conn(conn);
|
|
if(!circ) {
|
|
if(!circ) {
|
|
@@ -677,7 +771,7 @@ repeat_connection_package_raw_inbuf:
|
|
}
|
|
}
|
|
log(LOG_DEBUG,"connection_package_raw_inbuf(): receive_topicwindow at AP is %d",conn->p_receive_topicwindow);
|
|
log(LOG_DEBUG,"connection_package_raw_inbuf(): receive_topicwindow at AP is %d",conn->p_receive_topicwindow);
|
|
}
|
|
}
|
|
- if(amount_to_process > CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE) {
|
|
|
|
|
|
+ if (conn->inbuf_datalen) {
|
|
log(LOG_DEBUG,"connection_package_raw_inbuf(): recursing.");
|
|
log(LOG_DEBUG,"connection_package_raw_inbuf(): recursing.");
|
|
goto repeat_connection_package_raw_inbuf;
|
|
goto repeat_connection_package_raw_inbuf;
|
|
}
|
|
}
|