void evhttp_send_reply(struct evhttp_request *, int, const char *,
struct evbuffer *);
+/* Low-level response interface, for streaming/chunked replies */
+void evhttp_send_reply_start(struct evhttp_request *, int, const char *);
+void evhttp_send_reply_data(struct evhttp_request *, struct evbuffer *);
+void evhttp_send_reply_done(struct evhttp_request *);
+
/* Interfaces for making requests */
enum evhttp_cmd_type { EVHTTP_REQ_GET, EVHTTP_REQ_POST, EVHTTP_REQ_HEAD };
void evhttp_connection_set_retries(struct evhttp_connection *evcon,
int retry_max);
+/* Set a callback for connection close. */
+void evhttp_connection_set_closecb(struct evhttp_connection *evcon,
+ void (*)(struct evhttp_connection *, void *), void *);
+
+/* Get the remote address and port associated with this connection. */
+void evhttp_connection_get_peer(struct evhttp_connection *evcon,
+ char **address, u_short *port);
+
/* The connection gets ownership of the request */
int evhttp_make_request(struct evhttp_connection *evcon,
struct evhttp_request *req,
}
/* Activate our call back */
- (*evcon->cb)(evcon, evcon->cb_arg);
+ if (evcon->cb != NULL)
+ (*evcon->cb)(evcon, evcon->cb_arg);
}
void
{
struct evhttp_request *req;
+ /* notify interested parties that this connection is going down */
+ if (evcon->fd != -1) {
+ if (evcon->closecb != NULL)
+ (*evcon->closecb)(evcon, evcon->closecb_arg);
+ }
+
/* remove all requests that might be queued on this connection */
while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
TAILQ_REMOVE(&evcon->requests, req, next);
event_del(&evcon->ev);
if (evcon->fd != -1) {
+ /* inform interested parties about connection close */
+ if (evcon->closecb != NULL)
+ (*evcon->closecb)(evcon, evcon->closecb_arg);
+
close(evcon->fd);
evcon->fd = -1;
}
static void
evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
{
- assert((evcon->flags & EVHTTP_REQ_OWN_CONNECTION) == 0);
evcon->flags |= EVHTTP_CON_CLOSEDETECT;
event_del(&evcon->ev);
evcon->retry_max = retry_max;
}
+void
+evhttp_connection_set_closecb(struct evhttp_connection *evcon,
+ void (*cb)(struct evhttp_connection *, void *), void *cbarg)
+{
+ evcon->closecb = cb;
+ evcon->closecb_arg = cbarg;
+ /*
+ * xxx: we cannot just call evhttp_connection_start_detectclose here
+ * that's valid only for client initiated connections that currently
+ * do not process any requests.
+ */
+}
+
+void
+evhttp_connection_get_peer(struct evhttp_connection *evcon,
+ char **address, u_short *port)
+{
+ *address = evcon->address;
+ *port = evcon->port;
+}
+
int
evhttp_connection_connect(struct evhttp_connection *evcon)
{
evhttp_send(req, databuf);
}
+void
+evhttp_send_reply_start(struct evhttp_request *req, int code,
+ const char *reason)
+{
+ evhttp_response_code(req, code, reason);
+ evhttp_make_header(req->evcon, req);
+ evhttp_write_buffer(req->evcon, NULL, NULL);
+}
+
+void
+evhttp_send_reply_data(struct evhttp_request *req, struct evbuffer *databuf)
+{
+ evbuffer_add_buffer(req->evcon->output_buffer, databuf);
+ evhttp_write_buffer(req->evcon, NULL, NULL);
+}
+
+void
+evhttp_send_reply_done(struct evhttp_request *req)
+{
+ struct evhttp_connection *evcon = req->evcon;
+
+ if (!event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL)) {
+ /* let the connection know that we are done with the request */
+ evhttp_send_done(evcon, NULL);
+ } else {
+ /* make the callback execute after all data has been written */
+ evcon->cb = evhttp_send_done;
+ evcon->cb_arg = NULL;
+ }
+}
+
void
evhttp_response_code(struct evhttp_request *req, int code, const char *reason)
{