]> granicus.if.org Git - libevent/commitdiff
Implement interface that provides the ability to have an outbound evhttp_connection...
authorJohn Ohl <john@collabriasoftware.com>
Sun, 26 Oct 2014 05:18:10 +0000 (01:18 -0400)
committerJohn Ohl <john@collabriasoftware.com>
Sun, 26 Oct 2014 05:25:28 +0000 (01:25 -0400)
http-internal.h
http.c
include/event2/http.h

index 6f2f5b855d93c6ac31f0a3fe9cbbf3cd086a00ea..a83160c8341b8ae9e348f15526c13356c2581b7a 100644 (file)
@@ -74,6 +74,7 @@ struct evhttp_connection {
 #define EVHTTP_CON_INCOMING    0x0001  /* only one request on it ever */
 #define EVHTTP_CON_OUTGOING    0x0002  /* multiple requests possible */
 #define EVHTTP_CON_CLOSEDETECT  0x0004  /* detecting if persistent close */
+#define EVHTTP_CON_AUTOFREE 0x0008  /* set when we want to auto free the connection */
 
        struct timeval timeout;         /* timeout for events */
        int retry_cnt;                  /* retry count */
diff --git a/http.c b/http.c
index 3941d1790063328240e1cb4ceb65e07f41066093..e02297acef0b33aa8f124fcc22fe5b922a7b4b42 100644 (file)
--- a/http.c
+++ b/http.c
@@ -769,6 +769,7 @@ evhttp_connection_done(struct evhttp_connection *evcon)
 {
        struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
        int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
+       int free_evcon = 0;
 
        if (con_outgoing) {
                /* idle or close the connection */
@@ -801,6 +802,12 @@ evhttp_connection_done(struct evhttp_connection *evcon)
                         * need to detect if the other side closes it.
                         */
                        evhttp_connection_start_detectclose(evcon);
+               } else if ((evcon->flags & EVHTTP_CON_AUTOFREE)) {
+                       /*
+                        * If we have no more requests that need completion
+                        * and we're not waiting for the connection to close
+                        */
+                        free_evcon = 1;
                }
        } else {
                /*
@@ -819,6 +826,16 @@ evhttp_connection_done(struct evhttp_connection *evcon)
        if (con_outgoing && ((req->flags & EVHTTP_USER_OWNED) == 0)) {
                evhttp_request_free(req);
        }
+
+       /* If this was the last request of an outgoing connection and we're
+        * not waiting to receive a connection close event and we want to
+        * automatically free the connection. We check to ensure our request
+        * list is empty one last time just in case our callback added a
+        * new request.
+        */
+       if (free_evcon && TAILQ_FIRST(&evcon->requests) == NULL) {
+               evhttp_connection_free(evcon);
+       }
 }
 
 /*
@@ -1174,6 +1191,11 @@ evhttp_connection_free(struct evhttp_connection *evcon)
        mm_free(evcon);
 }
 
+void
+evhttp_connection_free_on_completion(struct evhttp_connection *evcon) {
+       evcon->flags |= EVHTTP_CON_AUTOFREE;
+}
+
 void
 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
     const char *address)
@@ -1385,6 +1407,17 @@ evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
                 */
                EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
                evhttp_connection_reset_(evcon);
+
+               /*
+                * If we have no more requests that need completion
+                * and we want to auto-free the connection when all
+                * requests have been completed.
+                */
+               if (TAILQ_FIRST(&evcon->requests) == NULL
+                 && (evcon->flags & EVHTTP_CON_OUTGOING)
+                 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
+                       evhttp_connection_free(evcon);
+               }
                return;
        }
 
index 7cade8777b9898f3a2c246876fdd3479c53d10db..4284d5fc32bc21bffb8cde93c4422930616d0a67 100644 (file)
@@ -675,6 +675,14 @@ void evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
 EVENT2_EXPORT_SYMBOL
 void evhttp_connection_free(struct evhttp_connection *evcon);
 
+/** Disowns a given connection object
+ *
+ * Can be used to tell libevent to free the connection object after
+ * the last request has completed or failed.
+ */
+EVENT2_EXPORT_SYMBOL
+void evhttp_connection_free_on_completion(struct evhttp_connection *evcon);
+
 /** sets the ip address from which http connections are made */
 EVENT2_EXPORT_SYMBOL
 void evhttp_connection_set_local_address(struct evhttp_connection *evcon,