|
@@ -52,7 +52,15 @@ pirprocess_stdoutcb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
|
|
if (handle->readstate == PIRPROCESS_READSTATE_HEADER) {
|
|
|
int res = read(fd, handle->hdrbuf + handle->readoff, handle->readleft);
|
|
|
- if (res <= 0) return;
|
|
|
+ if (res <= 0) {
|
|
|
+ /* Tell the caller that the PIR process failed to send us any output. */
|
|
|
+ tor_free(handle->bodybuf);
|
|
|
+ handle->readoff = 0;
|
|
|
+ handle->readleft = PIRPROCESS_HDR_SIZE;
|
|
|
+ handle->readstate = PIRPROCESS_READSTATE_HEADER;
|
|
|
+ (handle->msghandler)(NULL, NULL, 0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
handle->readoff += res;
|
|
|
handle->readleft -= res;
|
|
|
if (handle->readleft == 0) {
|
|
@@ -74,7 +82,15 @@ pirprocess_stdoutcb(evutil_socket_t fd, short what, void *arg)
|
|
|
} else if (handle->readstate == PIRPROCESS_READSTATE_BODY) {
|
|
|
int res = read(fd, handle->bodybuf + handle->readoff,
|
|
|
handle->readleft);
|
|
|
- if (res <= 0) return;
|
|
|
+ if (res <= 0) {
|
|
|
+ /* Tell the caller that the PIR process failed to send us any output. */
|
|
|
+ tor_free(handle->bodybuf);
|
|
|
+ handle->readoff = 0;
|
|
|
+ handle->readleft = PIRPROCESS_HDR_SIZE;
|
|
|
+ handle->readstate = PIRPROCESS_READSTATE_HEADER;
|
|
|
+ (handle->msghandler)(NULL, NULL, 0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
handle->readoff += res;
|
|
|
handle->readleft -= res;
|
|
|
if (handle->readleft == 0) {
|
|
@@ -301,7 +317,7 @@ int
|
|
|
hs_pirprocess_send(pir_process_t handle, const unsigned char *buf,
|
|
|
size_t len)
|
|
|
{
|
|
|
- if (handle->process == NULL ||
|
|
|
+ if (handle == NULL || handle->process == NULL ||
|
|
|
handle->process->status != PROCESS_STATUS_RUNNING) {
|
|
|
/* We don't have a process to talk to */
|
|
|
return -1;
|
|
@@ -315,11 +331,16 @@ hs_pirprocess_send(pir_process_t handle, const unsigned char *buf,
|
|
|
return len;
|
|
|
}
|
|
|
|
|
|
-/* What we really want is a map from uint64_t to dir_connection_t*, but
|
|
|
- * we've got an implementation of char[20] to void*, which we'll
|
|
|
- * repurpose for this use. Note that the dir_connection_t* pointers in
|
|
|
- * this map are *not* owned by this map, and this map must not free
|
|
|
- * them. */
|
|
|
+typedef struct {
|
|
|
+ dir_connection_t *conn;
|
|
|
+ pir_process_abort_fn abort_fn;
|
|
|
+} pirprocess_digestmap_entry_t;
|
|
|
+
|
|
|
+/* What we really want is a map from uint64_t to
|
|
|
+ * pirprocess_digestmap_entry_t*, but we've got an implementation of
|
|
|
+ * char[20] to void*, which we'll repurpose for this use. Note that the
|
|
|
+ * dir_connection_t* pointers in this map are *not* owned by this map,
|
|
|
+ * and this map must not free them. */
|
|
|
static digestmap_t *pirprocess_reqid_map;
|
|
|
|
|
|
/* The last-used request id */
|
|
@@ -332,16 +353,35 @@ hs_pirprocess_init(void)
|
|
|
pirprocess_last_reqid = 0;
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+entry_abort_free(void *p)
|
|
|
+{
|
|
|
+ pirprocess_digestmap_entry_t *entry = (pirprocess_digestmap_entry_t *)p;
|
|
|
+ if (entry->abort_fn) {
|
|
|
+ (entry->abort_fn)(entry->conn);
|
|
|
+ }
|
|
|
+ tor_free(entry);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+hs_pirprocess_abort_all(void)
|
|
|
+{
|
|
|
+ digestmap_free(pirprocess_reqid_map, entry_abort_free);
|
|
|
+ hs_pirprocess_init();
|
|
|
+}
|
|
|
+
|
|
|
void
|
|
|
hs_pirprocess_free_all(void)
|
|
|
{
|
|
|
- digestmap_free(pirprocess_reqid_map, NULL);
|
|
|
+ digestmap_free(pirprocess_reqid_map, tor_free_);
|
|
|
}
|
|
|
|
|
|
uint64_t
|
|
|
-hs_pirprocess_alloc_reqid(dir_connection_t *dir_conn)
|
|
|
+hs_pirprocess_alloc_reqid(dir_connection_t *dir_conn,
|
|
|
+ pir_process_abort_fn abort_fn)
|
|
|
{
|
|
|
char mapbuf[DIGEST_LEN];
|
|
|
+ pirprocess_digestmap_entry_t *entry;
|
|
|
uint64_t reqid = dir_conn->pirprocess_reqid;
|
|
|
if (reqid > 0) {
|
|
|
return reqid;
|
|
@@ -354,7 +394,10 @@ hs_pirprocess_alloc_reqid(dir_connection_t *dir_conn)
|
|
|
reqid = pirprocess_last_reqid;
|
|
|
memset(mapbuf, 0, DIGEST_LEN);
|
|
|
memmove(mapbuf, &reqid, sizeof(reqid));
|
|
|
- digestmap_set(pirprocess_reqid_map, mapbuf, dir_conn);
|
|
|
+ entry = tor_malloc(sizeof(*entry));
|
|
|
+ entry->conn = dir_conn;
|
|
|
+ entry->abort_fn = abort_fn;
|
|
|
+ digestmap_set(pirprocess_reqid_map, mapbuf, entry);
|
|
|
dir_conn->pirprocess_reqid = reqid;
|
|
|
return dir_conn->pirprocess_reqid;
|
|
|
}
|
|
@@ -364,10 +407,12 @@ hs_pirprocess_dealloc_reqid(dir_connection_t *dir_conn)
|
|
|
{
|
|
|
char mapbuf[DIGEST_LEN];
|
|
|
uint64_t reqid = dir_conn->pirprocess_reqid;
|
|
|
+ pirprocess_digestmap_entry_t *entry;
|
|
|
if (reqid == 0) return;
|
|
|
memset(mapbuf, 0, DIGEST_LEN);
|
|
|
memmove(mapbuf, &reqid, sizeof(reqid));
|
|
|
- digestmap_remove(pirprocess_reqid_map, mapbuf);
|
|
|
+ entry = digestmap_remove(pirprocess_reqid_map, mapbuf);
|
|
|
+ tor_free(entry);
|
|
|
dir_conn->pirprocess_reqid = 0;
|
|
|
}
|
|
|
|
|
@@ -375,9 +420,9 @@ dir_connection_t *
|
|
|
hs_pirprocess_lookup_reqid(uint64_t reqid)
|
|
|
{
|
|
|
char mapbuf[DIGEST_LEN];
|
|
|
- dir_connection_t *dir_conn;
|
|
|
+ pirprocess_digestmap_entry_t *entry;
|
|
|
memset(mapbuf, 0, DIGEST_LEN);
|
|
|
memmove(mapbuf, &reqid, sizeof(reqid));
|
|
|
- dir_conn = digestmap_get(pirprocess_reqid_map, mapbuf);
|
|
|
- return dir_conn;
|
|
|
+ entry = digestmap_get(pirprocess_reqid_map, mapbuf);
|
|
|
+ return entry->conn;
|
|
|
}
|