void EvHttpSyncClient::post(const std::string& sURI, const std::string& sData) { struct evhttp_request* pReq = newReqest(); if (!pReq) { return; } int rv = evbuffer_add(evhttp_request_get_output_buffer(pReq), sData.c_str(), sData.length()); if (rv != 0) { setError(ST_ERROR, "evhttp_add_buffer FAILED"); return; } rv = evhttp_make_request(m_pConn, pReq, EVHTTP_REQ_POST, sURI.c_str()); if (rv != 0) { setError(ST_ERROR, "evhttp_make_request FAILED"); return; } rv = event_base_dispatch(m_evbase); if (rv != 0) { FX_LOG(WARN, "event loop failed: [%d]", rv); } }
static int upnpc_get_desc(upnpc_device_t * d, const char * url) { char hostname[MAXHOSTNAMELEN+1]; char hostname_port[MAXHOSTNAMELEN+1+6]; unsigned short port; char * path; unsigned int scope_id; struct evhttp_request * req; struct evkeyvalq * headers; /* if(d->root_desc_location == NULL) { return -1; } */ if(!parseURL(url/*d->root_desc_location*/, hostname, &port, &path, &scope_id)) { return -1; } if(port != 80) snprintf(hostname_port, sizeof(hostname_port), "%s:%hu", hostname, port); else strncpy(hostname_port, hostname, sizeof(hostname_port)); if(d->desc_conn == NULL) { d->desc_conn = evhttp_connection_base_new(d->parent->base, NULL, hostname, port); } #ifdef DEBUG evhttp_connection_set_closecb(d->desc_conn, upnpc_conn_close_cb, d); #endif /* DEBUG */ /*evhttp_connection_set_timeout(p->desc_conn, 600);*/ req = evhttp_request_new(upnpc_desc_received/*callback*/, d); headers = evhttp_request_get_output_headers(req); evhttp_add_header(headers, "Host", hostname_port); evhttp_add_header(headers, "Connection", "close"); /*evhttp_add_header(headers, "User-Agent", "***");*/ return evhttp_make_request(d->desc_conn, req, EVHTTP_REQ_GET, path); }
void EvHttpSyncClient::get(const std::string& sURI) { struct evhttp_request* pReq = newReqest(); if (!pReq) { setError(ST_ERROR, "new request FAILED"); return ; } int rv = evhttp_make_request(m_pConn, pReq, EVHTTP_REQ_GET, sURI.c_str()); if (rv != 0) { FX_LOG(ERROR, "evhttp_make_request FAILED"); setError(ST_ERROR, "evhttp_make_request FAILED"); return; } rv = event_base_dispatch(m_evbase); if (rv != 0) { setError(ST_ERROR, "event loop failed"); FX_LOG(ERROR, "event loop failed: [%d]", rv); } FX_TRACE("made request: [%s]", sURI.c_str()); return ; }
static void perform_ssl_connection (void) { struct evhttp_connection *con; struct evhttp_request *req; struct bufferevent *bev; SSL_CTX *sctx; SSL *ssl; sctx = SSL_CTX_new (SSLv23_client_method ()); assert (sctx); SSL_CTX_set_options (sctx, SSL_OP_NO_TLSv1_2); //SSL_CTX_set_options (sctx, SSL_OP_ALL); SSL_CTX_set_timeout (sctx, 3000); SSL_CTX_set_verify (sctx, SSL_VERIFY_PEER, SSLX_CTX_verify_callback); SSL_CTX_set_default_verify_paths (sctx); SSL_CTX_set_cipher_list (sctx, "RC4-MD5"); ssl = SSL_new (sctx); assert (ssl); bev = bufferevent_openssl_socket_new (evbase, -1, ssl, BUFFEREVENT_SSL_CONNECTING , BEV_OPT_CLOSE_ON_FREE); //bev = bufferevent_socket_new (evbase, -1, BEV_OPT_CLOSE_ON_FREE); assert (bev); con = evhttp_connection_base_bufferevent_new (evbase, dnsbase, bev, HOST, PORT); evhttp_connection_set_closecb (con, on_connection_close, NULL); evhttp_connection_set_timeout (con, 10); req = evhttp_request_new (on_response_cb, NULL); evhttp_add_header (req->output_headers, "Host", HOST); // evhttp_add_header (req->output_headers, "Connection", "Keep-Alive"); evhttp_make_request (con, req, EVHTTP_REQ_GET, "/index.html"); }
void URLConnection::request( const std::string& url, URLConnectionCompleteCB callback, void* callback_data ) /// /// Function to request a page via the GET protocol /// /// @param url /// The url to request (note, this does NOT include the host) /// /// @param callback /// Callback to call on success / failure of the request /// /// @param callback_data /// Data to send back with callback /// { // create a struct for handling the real callback for the user of URLConnection // should be deallocated in the url_connection_callback function ConnectionCallbackData* cb_data = new ConnectionCallbackData(); cb_data->callback = callback; cb_data->data = callback_data; evhttp_request* request = evhttp_request_new(url_connection_callback, cb_data); // set up appropriate headers for a GET request char* host_address; ev_uint16_t port; evhttp_connection_get_peer(mConnection, &host_address, &port); evhttp_add_header( request->output_headers, "Host", host_address ); evhttp_add_header( request->output_headers, "User-Agent", mUserAgent.c_str() ); evhttp_make_request(mConnection, request, EVHTTP_REQ_GET, url.c_str()); }
void dispatch(runner *run, int reqno) { struct evhttp_connection *evcon = run->evcon; struct evhttp_request *evreq; struct request *req; if((req = calloc(1, sizeof(*req))) == nil) panic("calloc"); run->req = req; req->evcon = evcon; req->evcon_reqno = reqno; evreq = evhttp_request_new(&recvcb, run); if(evreq == nil) panic("evhttp_request_new"); req->evreq = evreq; evreq->response_code = -1; evhttp_add_header(evreq->output_headers, "Host", http_hosthdr); gettimeofday(&req->starttv, nil); evtimer_set(&req->timeoutev, timeoutcb, run); evtimer_add(&req->timeoutev, &timeouttv); debug("dispatch(): evtimer_add(&req->timeoutev, &timeouttv);\n"); counts.conns++; evhttp_make_request(evcon, evreq, EVHTTP_REQ_GET, params.path); }
void dispatch(struct evhttp_connection *evcon, int reqno) { struct evhttp_request *evreq; struct request *req; char *request_uri; if((req = calloc(1, sizeof(*req))) == nil) panic("calloc"); req->evcon = evcon; req->evcon_reqno = reqno; evreq = evhttp_request_new(&recvcb, req); if(evreq == nil) panic("evhttp_request_new"); req->evreq = evreq; evreq->response_code = -1; evhttp_add_header(evreq->output_headers, "Host", http_hosthdr); gettimeofday(&req->starttv, nil); evtimer_set(&req->timeoutev, timeoutcb,(void *)req); evtimer_add(&req->timeoutev, &timeouttv); request_uri = "/"; if (num_requests > 0) { request_uri = requests[cur_request++]; cur_request = cur_request % (num_requests + 1); } evhttp_make_request(evcon, evreq, EVHTTP_REQ_GET, request_uri); }
/** * pthread entry point, running the reader event base. */ void * comet_run_readers(void *ptr) { struct reader_thread *rt = ptr; int i, j; rt->base = event_base_new(); for(i = 0; i < rt->channel_count; ++i) { char *chan = rt->channels[i]; char *url = calloc(strlen(chan) + 17, 1); sprintf(url, "/subscribe?name=%s", chan); for(j = 0; j < rt->reader_per_chan; ++j) { struct evhttp_connection *evcon = evhttp_connection_new(rt->hi->host, rt->hi->port); struct evhttp_request *evreq = evhttp_request_new(on_end_of_subscribe, rt); evhttp_connection_set_base(evcon, rt->base); evhttp_request_set_chunked_cb(evreq, on_http_message_chunk); evhttp_make_request(evcon, evreq, EVHTTP_REQ_GET, url); /* printf("[SUBSCRIBE: http://127.0.0.1:1234%s]\n", url); */ } } event_base_dispatch(rt->base); return NULL; }
static void http_close_detection(int with_delay) { short port = -1; struct evhttp_connection *evcon = NULL; struct evhttp_request *req = NULL; test_ok = 0; fprintf(stdout, "Testing Connection Close Detection%s: ", with_delay ? " (with delay)" : ""); http = http_setup(&port, NULL); /* 2 second timeout */ evhttp_set_timeout(http, 2); evcon = evhttp_connection_new("127.0.0.1", port); if (evcon == NULL) { fprintf(stdout, "FAILED\n"); exit(1); } delayed_client = evcon; /* * At this point, we want to schedule a request to the HTTP * server using our make request method. */ req = evhttp_request_new(close_detect_cb, evcon); /* Add the information that we care about */ evhttp_add_header(req->output_headers, "Host", "somehost"); /* We give ownership of the request to the connection */ if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, with_delay ? "/largedelay" : "/test") == -1) { fprintf(stdout, "FAILED\n"); exit(1); } event_dispatch(); if (test_ok != 1) { fprintf(stdout, "FAILED\n"); exit(1); } /* at this point, the http server should have no connection */ if (TAILQ_FIRST(&http->connections) != NULL) { fprintf(stdout, "FAILED (left connections)\n"); exit(1); } evhttp_connection_free(evcon); evhttp_free(http); fprintf(stdout, "OK\n"); }
virtual void SetUp() { handler_.reset(new HTTPHandler(&DoMyFunc)); base_ = event_base_new(); dnsbase_ = evdns_base_new(base_, 1); connection_ = evhttp_connection_base_new(base_, dnsbase_, "0.0.0.0", 8080); request_ = evhttp_request_new(NULL, NULL); evhttp_make_request(connection_, request_, EVHTTP_REQ_GET, ""); }
void create_request(const char *url) { struct evhttp_uri *http_uri = NULL; const char *host; struct bufferevent *bev; struct evhttp_connection *evcon = NULL; struct evhttp_request *req; struct evkeyvalq *output_headers; http_uri = evhttp_uri_parse(url); if (NULL != http_uri) { host = evhttp_uri_get_host(http_uri); if (NULL != host) { bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE); evcon = evhttp_connection_base_bufferevent_new(base, dnsbase, bev, host, HTTP_PORT); if (NULL != evcon) { evhttp_connection_set_timeout(evcon, TIMEOUT); req = evhttp_request_new(http_request_done, bev); if (NULL != req) { output_headers = evhttp_request_get_output_headers(req); evhttp_add_header(output_headers, "Accept", "text/plain;q=0.8"); evhttp_add_header(output_headers, "Host", host); evhttp_add_header(output_headers, "User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"); evhttp_add_header(output_headers, "Connection", "close"); if (0 == evhttp_make_request(evcon, req, EVHTTP_REQ_GET, url)) { ++n_pending_requests; } else { evhttp_request_free(req); fprintf(stderr, "evhttp_make_request() failed\n"); } //evhttp_request_free(req); } else { fprintf(stderr, "evhttp_request_new() failed\n"); } //evhttp_connection_free(evcon); } else { fprintf(stderr, "evhttp_connection_base_bufferevent_new() failed\n"); } } else { fprintf(stderr, "url must have a host %s\n", url); } evhttp_uri_free(http_uri); } else { fprintf(stderr, "malformed url %s\n", url); } }
void HttpClient_YPL::post() { //char *url = "/portal/sss"; char *url = "/api/service"; struct evhttp_request *req = evhttp_request_new(onRequestDone, this); evhttp_add_header(req->output_headers, "Host", m_host.c_str()); evhttp_make_request(m_conn, req, EVHTTP_REQ_POST, url); evhttp_connection_set_timeout(req->evcon, 3); evhttp_connection_set_closecb(req->evcon, onClose, this); //evbuffer_add(req->output_buffer, "123", 3); event_base_dispatch(m_base); }
int upnpc_event_subscribe(upnpc_device_t * p) { char hostname[MAXHOSTNAMELEN+1]; char hostname_port[MAXHOSTNAMELEN+1+6]; unsigned short port; char * path; unsigned int scope_id; struct evhttp_request * req; struct evkeyvalq * headers; char callback_header[7+15+1+5+9+2+1]; if(p->parent->http_server == NULL) { /* HTTP server to receive event notifications */ p->parent->http_server = evhttp_new(p->parent->base); if(p->parent->http_server == NULL) { debug_printf("evhttp_new() FAILED\n"); return -1; } evhttp_set_ext_method_cmp(p->parent->http_server, ext_methods_cb); evhttp_set_allowed_methods(p->parent->http_server, EVHTTP_REQ_NOTIFY); evhttp_set_cb(p->parent->http_server, "/evt_conn", upnpc_event_conn_req, p); if(evhttp_bind_socket(p->parent->http_server, p->parent->local_address, p->parent->local_port) < 0) { debug_printf("evhttp_bind_socket() FAILED\n"); return -1; } } /*if(!parseURL(p->event_cif_url, hostname, &port, &path, &scope_id)) {*/ if(!parseURL(p->event_conn_url, hostname, &port, &path, &scope_id)) { return -1; } if(port != 80) snprintf(hostname_port, sizeof(hostname_port), "%s:%hu", hostname, port); else strncpy(hostname_port, hostname, sizeof(hostname_port)); if(p->soap_conn == NULL) { p->soap_conn = evhttp_connection_base_new(p->parent->base, NULL, hostname, port); } evhttp_connection_set_ext_method_cmp(p->soap_conn, ext_methods_cb); req = evhttp_request_new(upnpc_subscribe_response, p); headers = evhttp_request_get_output_headers(req); /*buffer = evhttp_request_get_output_buffer(req);*/ evhttp_add_header(headers, "Host", hostname_port); /*evhttp_add_header(headers, "User-Agent", "***");*/ snprintf(callback_header, sizeof(callback_header), "<http://%s:%hu/evt_conn>", p->parent->local_address, p->parent->local_port); evhttp_add_header(headers, "Callback", callback_header); evhttp_add_header(headers, "NT", "upnp:event"); /*evhttp_add_header(headers, "NTS", "");*/ evhttp_add_header(headers, "Timeout", "3600"); /*evbuffer_add(buffer, body, body_len);*/ evhttp_make_request(p->soap_conn, req, EVHTTP_REQ_SUBSCRIBE, path); p->state |= UPNPC_DEVICE_SOAP_REQ; return 0; }
static void http_dispatcher_test(void) { short port = -1; struct evhttp_connection *evcon = NULL; struct evhttp_request *req = NULL; test_ok = 0; fprintf(stdout, "Testing HTTP Dispatcher: "); http = http_setup(&port, NULL); evcon = evhttp_connection_new("127.0.0.1", port); if (evcon == NULL) { fprintf(stdout, "FAILED\n"); exit(1); } /* also bind to local host */ evhttp_connection_set_local_address(evcon, "127.0.0.1"); /* * At this point, we want to schedule an HTTP GET request * server using our make request method. */ req = evhttp_request_new(http_dispatcher_test_done, NULL); if (req == NULL) { fprintf(stdout, "FAILED\n"); exit(1); } /* Add the information that we care about */ evhttp_add_header(req->output_headers, "Host", "somehost"); if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/?arg=val") == -1) { fprintf(stdout, "FAILED\n"); exit(1); } event_dispatch(); evhttp_connection_free(evcon); evhttp_free(http); if (test_ok != 1) { fprintf(stdout, "FAILED: %d\n", test_ok); exit(1); } fprintf(stdout, "OK\n"); }
static void http_post_test(void) { short port = -1; struct evhttp_connection *evcon = NULL; struct evhttp_request *req = NULL; test_ok = 0; fprintf(stdout, "Testing HTTP POST Request: "); http = http_setup(&port, NULL); evcon = evhttp_connection_new("127.0.0.1", port); if (evcon == NULL) { fprintf(stdout, "FAILED\n"); exit(1); } /* * At this point, we want to schedule an HTTP POST request * server using our make request method. */ req = evhttp_request_new(http_postrequest_done, NULL); if (req == NULL) { fprintf(stdout, "FAILED\n"); exit(1); } /* Add the information that we care about */ evhttp_add_header(req->output_headers, "Host", "somehost"); evbuffer_add_printf(req->output_buffer, POST_DATA); if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) { fprintf(stdout, "FAILED\n"); exit(1); } event_dispatch(); evhttp_connection_free(evcon); evhttp_free(http); if (test_ok != 1) { fprintf(stdout, "FAILED: %d\n", test_ok); exit(1); } fprintf(stdout, "OK\n"); }
int pubsub_to_pubsub_main_path(char *source_address, int source_port, char *target_address, int target_port, int (*cb)(char *data, struct evbuffer *evb, char **target_path, void *arg), void *cbarg, char *target_path) { event_init(); struct evhttp_connection *evhttp_source_connection = NULL; struct evhttp_connection *evhttp_target_connection = NULL; struct evhttp_request *evhttp_source_request = NULL; fprintf(stdout, "connecting to http://%s:%d/sub\n", source_address, source_port); evhttp_source_connection = evhttp_connection_new(source_address, source_port); if (evhttp_source_connection == NULL) { fprintf(stdout, "FAILED CONNECT TO SOURCE %s:%d\n", source_address, source_port); exit(1); } fprintf(stdout, "connecting to http://%s:%d/pub\n", target_address, target_port); evhttp_target_connection = evhttp_connection_new(target_address, target_port); if (evhttp_target_connection == NULL) { fprintf(stdout, "FAILED CONNECT TO TARGET %s:%d\n", target_address, target_port); exit(1); } struct global_data *data; data = calloc(1, sizeof(*data)); data->evhttp_target_connection = evhttp_target_connection; data->target_address = target_address; data->target_path = calloc(4096, sizeof(char *)); strcpy(data->target_path, target_path); data->cb = cb; data->cbarg = cbarg; evhttp_source_request = evhttp_request_new(http_chunked_request_done, data); evhttp_add_header(evhttp_source_request->output_headers, "Host", source_address); evhttp_request_set_chunked_cb(evhttp_source_request, source_callback); if (evhttp_make_request(evhttp_source_connection, evhttp_source_request, EVHTTP_REQ_GET, "/sub") == -1) { fprintf(stdout, "FAILED make_request to source\n"); exit(1); } event_dispatch(); evhttp_connection_free(evhttp_source_connection); evhttp_connection_free(evhttp_target_connection); fprintf(stdout, "EXITING\n"); return 0; }
static void close_detect_launch(int fd, short what, void *arg) { struct evhttp_connection *evcon = arg; struct evhttp_request *req; req = evhttp_request_new(close_detect_done, NULL); /* Add the information that we care about */ evhttp_add_header(req->output_headers, "Host", "somehost"); /* We give ownership of the request to the connection */ if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { fprintf(stdout, "FAILED\n"); exit(1); } }
static void http_negative_content_length_test(void) { short port = -1; struct evhttp_connection *evcon = NULL; struct evhttp_request *req = NULL; test_ok = 0; fprintf(stdout, "Testing HTTP Negative Content Length: "); http = http_setup(&port, NULL); evcon = evhttp_connection_new("127.0.0.1", port); if (evcon == NULL) { fprintf(stdout, "FAILED\n"); exit(1); } /* * At this point, we want to schedule a request to the HTTP * server using our make request method. */ req = evhttp_request_new(http_request_bad, NULL); /* Cause the response to have a negative content-length */ evhttp_add_header(req->output_headers, "X-Negative", "makeitso"); /* We give ownership of the request to the connection */ if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { fprintf(stdout, "FAILED\n"); exit(1); } event_dispatch(); evhttp_free(http); if (test_ok != 1) { fprintf(stdout, "FAILED\n"); exit(1); } fprintf(stdout, "OK\n"); }
void runcb(int fd, short what, void *arg) { Run *run; Request *r; Call *c; Header *h; struct evhttp_connection *conn; struct evhttp_request *req; enum evhttp_cmd_type cmd; int i; run = (Run*)arg; r = &run->rs[rand() % run->rsiz]; if(run->cachedconn!=nil){ conn = run->cachedconn; run->cachedconn = nil; }else conn = mkconn(run->host, run->port); c = mal(sizeof(*c)); c->run = run; c->conn = conn; req = evhttp_request_new(&donecb, c); if(strcasecmp(r->action, "get")==0) cmd = EVHTTP_REQ_GET; else if(strcasecmp(r->action, "post")==0) cmd = EVHTTP_REQ_POST; else panic("invalid action \"%s\"", r->action); for(i=0;i<r->nheader;i++){ h = &r->headers[i]; evhttp_add_header( req->output_headers, h->key, h->value); } evhttp_make_request(conn, req, cmd, r->uri); event_add(&run->ev, &run->tv); }
static void rpc_grneral_request(char *ip, int port, const char *rpcname, void *req, marshal_func req_marshal, void *resp, unmarshal_func resp_unmarshal) { struct evhttp_connection *evcon = connection_pool_get_or_create_conn(conn_pool, ip, port); struct evhttp_request *evreq = evhttp_request_new(rpc_rpc_grneral_requestuest_cb, NULL); evhttp_request_own(evreq); // this means that I should free it my self req_marshal(evreq->output_buffer, req); if (evhttp_make_request(evcon, evreq, EVHTTP_REQ_POST, rpcname)) logging(LOG_ERROR, "error on make_request"); event_dispatch();//TODO if (resp_unmarshal(resp, evreq->input_buffer)) { logging(LOG_ERROR, "error on statfs_response_unmarshal"); } connection_pool_insert(conn_pool, ip, port, evcon); evhttp_request_free(evreq); }
bool TEvhttpClientChannel::sendAndRecvMessage( const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* sendBuf, apache::thrift::transport::TMemoryBuffer* recvBuf) { cob_ = cob; recvBuf_ = recvBuf; struct evhttp_request* req = evhttp_request_new(response, this); if (req == NULL) { abort(); // XXX } int rv; rv = evhttp_add_header(req->output_headers, "Host", host_.c_str()); if (rv != 0) { abort(); // XXX } rv = evhttp_add_header(req->output_headers, "Content-Type", "application/x-thrift"); if (rv != 0) { abort(); // XXX } uint8_t* obuf; uint32_t sz; sendBuf->getBuffer(&obuf, &sz); rv = evbuffer_add(req->output_buffer, obuf, sz); if (rv != 0) { abort(); // XXX } rv = evhttp_make_request(conn_, req, EVHTTP_REQ_POST, path_.c_str()); if (rv != 0) { abort(); // XXX } return true; }
void source_callback (struct evhttp_request *req, void *arg){ if (DEBUG) fprintf(stdout, "source_callback\n"); // enum message_read_status done; evhttp_clear_headers(req->input_headers); evhttp_parse_headers(req, req->input_buffer); char *content_len; content_len = (char *) evhttp_find_header(req->input_headers, "Content-Length"); if (!content_len){return;} int len = atoi(content_len); size_t len_size; len_size = (size_t)len; if (DEBUG) fprintf(stdout, "received content_length:%d buffer has:%d\n", len, EVBUFFER_LENGTH(req->input_buffer)); struct global_data *client_data = (struct global_data *)arg; struct evhttp_request *evhttp_target_request = NULL; evhttp_target_request = evhttp_request_new(http_post_done, NULL); evhttp_add_header(evhttp_target_request->output_headers, "Host", client_data->target_address); char *data = calloc(len, sizeof(char *)); evbuffer_remove(req->input_buffer, data, len); if (DEBUG)fprintf(stdout, "data has %d bytes\n", strlen(data)); if (DEBUG)fprintf(stdout, "data=%s\n", data); // empty buffer evbuffer_drain(req->input_buffer, EVBUFFER_LENGTH(req->input_buffer)); // write to output buffer int flag = (*client_data->cb)(data, evhttp_target_request->output_buffer, &client_data->target_path, client_data->cbarg); free(data); if (!flag){return;} // don't make the request if (evhttp_make_request(client_data->evhttp_target_connection, evhttp_target_request, EVHTTP_REQ_POST, client_data->target_path) == -1) { fprintf(stdout, "FAILED make_request\n"); exit(1); } }
void URLConnection::requestPOST(const std::string& url, const std::string& payload, URLConnectionCompleteCB callback, void* callback_data ) /// /// Function to request a page via the POST protocol /// /// @param url /// The url to request (note, this does NOT include the host) /// /// @param payload /// POST payload to send /// /// @param callback /// Callback to call on success / failure of the request /// /// @param callback_data /// Data to send back with callback /// { // create a struct for handling the real callback for the user of URLConnection // should be deallocated in the url_connection_callback function ConnectionCallbackData* cb_data = new ConnectionCallbackData(); cb_data->callback = callback; cb_data->data = callback_data; evhttp_request* request = evhttp_request_new(url_connection_callback, cb_data); // set up appropriate headers for a GET request char* host_address; ev_uint16_t port; evhttp_connection_get_peer(mConnection, &host_address, &port); evhttp_add_header( request->output_headers, "Host", host_address ); evhttp_add_header( request->output_headers, "User-Agent", mUserAgent.c_str() ); evhttp_add_header( request->output_headers, "Connection", "keep-alive" ); evhttp_add_header( request->output_headers, "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8" ); evbuffer_add(request->output_buffer, payload.c_str(), payload.size()); evhttp_make_request(mConnection, request, EVHTTP_REQ_POST, url.c_str()); }
void http_request::renew_request() { /* free connections & request */ if (m_cn) evhttp_connection_free(m_cn); #if !defined(_EVENT_NUMERIC_VERSION) || _EVENT_NUMERIC_VERSION < 0x02000000 m_cn = evhttp_connection_new(m_host.c_str(), m_port); evhttp_connection_set_base(m_cn, m_base); #else m_cn = evhttp_connection_base_new( m_base, NULL, m_host.c_str(), m_port); #endif m_req = evhttp_request_new(http_request::download_callback, this); evhttp_make_request(m_cn, m_req, m_type, m_query.c_str()); evhttp_add_header(m_req->output_headers, "Host", m_host.c_str()); }
static void http_chunked_test(void) { struct bufferevent *bev; int fd; const char *http_request; short port = -1; struct timeval tv_start, tv_end; struct evhttp_connection *evcon = NULL; struct evhttp_request *req = NULL; int i; test_ok = 0; fprintf(stdout, "Testing Chunked HTTP Reply: "); http = http_setup(&port, NULL); fd = http_connect("127.0.0.1", port); /* Stupid thing to send a request */ bev = bufferevent_new(fd, http_chunked_readcb, http_chunked_writecb, http_chunked_errorcb, NULL); http_request = "GET /chunked HTTP/1.1\r\n" "Host: somehost\r\n" "Connection: close\r\n" "\r\n"; bufferevent_write(bev, http_request, strlen(http_request)); evutil_gettimeofday(&tv_start, NULL); event_dispatch(); evutil_gettimeofday(&tv_end, NULL); evutil_timersub(&tv_end, &tv_start, &tv_end); if (tv_end.tv_sec >= 1) { fprintf(stdout, "FAILED (time)\n"); exit (1); } if (test_ok != 2) { fprintf(stdout, "FAILED\n"); exit(1); } /* now try again with the regular connection object */ evcon = evhttp_connection_new("127.0.0.1", port); if (evcon == NULL) { fprintf(stdout, "FAILED\n"); exit(1); } /* make two requests to check the keepalive behavior */ for (i = 0; i < 2; i++) { test_ok = 0; req = evhttp_request_new(http_chunked_request_done, NULL); /* Add the information that we care about */ evhttp_add_header(req->output_headers, "Host", "somehost"); /* We give ownership of the request to the connection */ if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/chunked") == -1) { fprintf(stdout, "FAILED\n"); exit(1); } event_dispatch(); if (test_ok != 1) { fprintf(stdout, "FAILED\n"); exit(1); } } evhttp_connection_free(evcon); evhttp_free(http); fprintf(stdout, "OK\n"); }
static void http_connection_test(int persistent) { short port = -1; struct evhttp_connection *evcon = NULL; struct evhttp_request *req = NULL; test_ok = 0; fprintf(stdout, "Testing Request Connection Pipeline %s: ", persistent ? "(persistent)" : ""); http = http_setup(&port, NULL); evcon = evhttp_connection_new("127.0.0.1", port); if (evcon == NULL) { fprintf(stdout, "FAILED\n"); exit(1); } /* * At this point, we want to schedule a request to the HTTP * server using our make request method. */ req = evhttp_request_new(http_request_done, NULL); /* Add the information that we care about */ evhttp_add_header(req->output_headers, "Host", "somehost"); /* We give ownership of the request to the connection */ if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { fprintf(stdout, "FAILED\n"); exit(1); } event_dispatch(); if (test_ok != 1) { fprintf(stdout, "FAILED\n"); exit(1); } /* try to make another request over the same connection */ test_ok = 0; req = evhttp_request_new(http_request_done, NULL); /* Add the information that we care about */ evhttp_add_header(req->output_headers, "Host", "somehost"); /* * if our connections are not supposed to be persistent; request * a close from the server. */ if (!persistent) evhttp_add_header(req->output_headers, "Connection", "close"); /* We give ownership of the request to the connection */ if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { fprintf(stdout, "FAILED\n"); exit(1); } event_dispatch(); /* make another request: request empty reply */ test_ok = 0; req = evhttp_request_new(http_request_empty_done, NULL); /* Add the information that we care about */ evhttp_add_header(req->output_headers, "Empty", "itis"); /* We give ownership of the request to the connection */ if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { fprintf(stdout, "FAILED\n"); exit(1); } event_dispatch(); if (test_ok != 1) { fprintf(stdout, "FAILED\n"); exit(1); } evhttp_connection_free(evcon); evhttp_free(http); fprintf(stdout, "OK\n"); }
static int upnpc_send_soap_request(upnpc_device_t * p, const char * url, const char * service, const char * method, const struct upnp_args * args, int arg_count) { char action[128]; char * body; const char fmt_soap[] = "<?xml version=\"1.0\"?>\r\n" "<" SOAPPREFIX ":Envelope " "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" " SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" "<" SOAPPREFIX ":Body>" "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">" "%s" "</" SERVICEPREFIX ":%s>" "</" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>" "\r\n"; int body_len; char hostname[MAXHOSTNAMELEN+1]; char hostname_port[MAXHOSTNAMELEN+1+6]; unsigned short port; char * path; unsigned int scope_id; char * args_xml = NULL; struct evhttp_request * req; struct evkeyvalq * headers; struct evbuffer * buffer; if(p->state & UPNPC_DEVICE_SOAP_REQ) { debug_printf("%s: another SOAP request in progress\n", __func__); return UPNPC_ERR_REQ_IN_PROGRESS; } if(arg_count > 0) { int i; size_t l, n; for(i = 0, l = 0; i < arg_count; i++) { /* <ELT>VAL</ELT> */ l += strlen(args[i].elt) * 2 + strlen(args[i].val) + 5; } args_xml = malloc(++l); if(args_xml == NULL) { return -1; } for(i = 0, n = 0; i < arg_count && n < l; i++) { /* <ELT>VAL</ELT> */ n += snprintf(args_xml + n, l - n, "<%s>%s</%s>", args[i].elt, args[i].val, args[i].elt); } } body_len = snprintf(NULL, 0, fmt_soap, method, service, args_xml?args_xml:"", method); body = malloc(body_len + 1); if(body == NULL) { free(args_xml); return -1; } if(snprintf(body, body_len + 1, fmt_soap, method, service, args_xml?args_xml:"", method) != body_len) { debug_printf("%s: snprintf() returned strange value...\n", __func__); } free(args_xml); args_xml = NULL; if(!parseURL(url, hostname, &port, &path, &scope_id)) { free(body); return -1; } if(port != 80) snprintf(hostname_port, sizeof(hostname_port), "%s:%hu", hostname, port); else strncpy(hostname_port, hostname, sizeof(hostname_port)); snprintf(action, sizeof(action), "\"%s#%s\"", service, method); if(p->soap_conn == NULL) { p->soap_conn = evhttp_connection_base_new(p->parent->base, NULL, hostname, port); } req = evhttp_request_new(upnpc_soap_response, p); headers = evhttp_request_get_output_headers(req); buffer = evhttp_request_get_output_buffer(req); evhttp_add_header(headers, "Host", hostname_port); evhttp_add_header(headers, "SOAPAction", action); evhttp_add_header(headers, "Content-Type", "text/xml"); /*evhttp_add_header(headers, "User-Agent", "***");*/ /*evhttp_add_header(headers, "Cache-Control", "no-cache");*/ /*evhttp_add_header(headers, "Pragma", "no-cache");*/ evbuffer_add(buffer, body, body_len); evhttp_make_request(p->soap_conn, req, EVHTTP_REQ_POST, path); free(body); p->state |= UPNPC_DEVICE_SOAP_REQ; return 0; }
static UniValue CallRPC(BaseRequestHandler *rh, const std::string& strMethod, const std::vector<std::string>& args) { std::string host; // In preference order, we choose the following for the port: // 1. -rpcport // 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6) // 3. default port for chain int port = BaseParams().RPCPort(); SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host); port = gArgs.GetArg("-rpcport", port); // Obtain event base raii_event_base base = obtain_event_base(); // Synchronously look up hostname raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port); evhttp_connection_set_timeout(evcon.get(), gArgs.GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT)); HTTPReply response; raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response); if (req == nullptr) throw std::runtime_error("create http request failed"); #if LIBEVENT_VERSION_NUMBER >= 0x02010300 evhttp_request_set_error_cb(req.get(), http_error_cb); #endif // Get credentials std::string strRPCUserColonPass; bool failedToGetAuthCookie = false; if (gArgs.GetArg("-rpcpassword", "") == "") { // Try fall back to cookie-based authentication if no password is provided if (!GetAuthCookie(&strRPCUserColonPass)) { failedToGetAuthCookie = true; } } else { strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", ""); } struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get()); assert(output_headers); evhttp_add_header(output_headers, "Host", host.c_str()); evhttp_add_header(output_headers, "Connection", "close"); evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str()); // Attach request data std::string strRequest = rh->PrepareRequest(strMethod, args).write() + "\n"; struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get()); assert(output_buffer); evbuffer_add(output_buffer, strRequest.data(), strRequest.size()); // check if we should use a special wallet endpoint std::string endpoint = "/"; if (!gArgs.GetArgs("-rpcwallet").empty()) { std::string walletName = gArgs.GetArg("-rpcwallet", ""); char *encodedURI = evhttp_uriencode(walletName.c_str(), walletName.size(), false); if (encodedURI) { endpoint = "/wallet/"+ std::string(encodedURI); free(encodedURI); } else { throw CConnectionFailed("uri-encode failed"); } } int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, endpoint.c_str()); req.release(); // ownership moved to evcon in above call if (r != 0) { throw CConnectionFailed("send http request failed"); } event_base_dispatch(base.get()); if (response.status == 0) { std::string responseErrorMessage; if (response.error != -1) { responseErrorMessage = strprintf(" (error code %d - \"%s\")", response.error, http_errorstring(response.error)); } throw CConnectionFailed(strprintf("Could not connect to the server %s:%d%s\n\nMake sure the bitcoind server is running and that you are connecting to the correct RPC port.", host, port, responseErrorMessage)); } else if (response.status == HTTP_UNAUTHORIZED) { if (failedToGetAuthCookie) { throw std::runtime_error(strprintf( "Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)", GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string().c_str())); } else { throw std::runtime_error("Authorization failed: Incorrect rpcuser or rpcpassword"); } } else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR) throw std::runtime_error(strprintf("server returned HTTP error %d", response.status)); else if (response.body.empty()) throw std::runtime_error("no response from server"); // Parse reply UniValue valReply(UniValue::VSTR); if (!valReply.read(response.body)) throw std::runtime_error("couldn't parse reply from server"); const UniValue reply = rh->ProcessReply(valReply); if (reply.empty()) throw std::runtime_error("expected reply to have result, error and id properties"); return reply; }
int main(int argc, char **argv) { int r; struct evhttp_uri *http_uri = NULL; const char *url = NULL, *data_file = NULL; const char *crt = "/etc/ssl/certs/ca-certificates.crt"; const char *scheme, *host, *path, *query; char uri[256]; int port; int retries = 0; int timeout = -1; SSL_CTX *ssl_ctx = NULL; SSL *ssl = NULL; struct bufferevent *bev; struct evhttp_connection *evcon = NULL; struct evhttp_request *req; struct evkeyvalq *output_headers; struct evbuffer *output_buffer; int i; int ret = 0; enum { HTTP, HTTPS } type = HTTP; for (i = 1; i < argc; i++) { if (!strcmp("-url", argv[i])) { if (i < argc - 1) { url = argv[i + 1]; } else { syntax(); goto error; } } else if (!strcmp("-crt", argv[i])) { if (i < argc - 1) { crt = argv[i + 1]; } else { syntax(); goto error; } } else if (!strcmp("-ignore-cert", argv[i])) { ignore_cert = 1; } else if (!strcmp("-data", argv[i])) { if (i < argc - 1) { data_file = argv[i + 1]; } else { syntax(); goto error; } } else if (!strcmp("-retries", argv[i])) { if (i < argc - 1) { retries = atoi(argv[i + 1]); } else { syntax(); goto error; } } else if (!strcmp("-timeout", argv[i])) { if (i < argc - 1) { timeout = atoi(argv[i + 1]); } else { syntax(); goto error; } } else if (!strcmp("-help", argv[i])) { syntax(); goto error; } } if (!url) { syntax(); goto error; } #ifdef _WIN32 { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { printf("WSAStartup failed with error: %d\n", err); goto error; } } #endif // _WIN32 http_uri = evhttp_uri_parse(url); if (http_uri == NULL) { err("malformed url"); goto error; } scheme = evhttp_uri_get_scheme(http_uri); if (scheme == NULL || (strcasecmp(scheme, "https") != 0 && strcasecmp(scheme, "http") != 0)) { err("url must be http or https"); goto error; } host = evhttp_uri_get_host(http_uri); if (host == NULL) { err("url must have a host"); goto error; } port = evhttp_uri_get_port(http_uri); if (port == -1) { port = (strcasecmp(scheme, "http") == 0) ? 80 : 443; } path = evhttp_uri_get_path(http_uri); if (strlen(path) == 0) { path = "/"; } query = evhttp_uri_get_query(http_uri); if (query == NULL) { snprintf(uri, sizeof(uri) - 1, "%s", path); } else { snprintf(uri, sizeof(uri) - 1, "%s?%s", path, query); } uri[sizeof(uri) - 1] = '\0'; #if OPENSSL_VERSION_NUMBER < 0x10100000L // Initialize OpenSSL SSL_library_init(); ERR_load_crypto_strings(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); #endif /* This isn't strictly necessary... OpenSSL performs RAND_poll * automatically on first use of random number generator. */ r = RAND_poll(); if (r == 0) { err_openssl("RAND_poll"); goto error; } /* Create a new OpenSSL context */ ssl_ctx = SSL_CTX_new(SSLv23_method()); if (!ssl_ctx) { err_openssl("SSL_CTX_new"); goto error; } #ifndef _WIN32 /* TODO: Add certificate loading on Windows as well */ /* Attempt to use the system's trusted root certificates. * (This path is only valid for Debian-based systems.) */ if (1 != SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL)) { err_openssl("SSL_CTX_load_verify_locations"); goto error; } /* Ask OpenSSL to verify the server certificate. Note that this * does NOT include verifying that the hostname is correct. * So, by itself, this means anyone with any legitimate * CA-issued certificate for any website, can impersonate any * other website in the world. This is not good. See "The * Most Dangerous Code in the World" article at * https://crypto.stanford.edu/~dabo/pubs/abstracts/ssl-client-bugs.html */ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); /* This is how we solve the problem mentioned in the previous * comment. We "wrap" OpenSSL's validation routine in our * own routine, which also validates the hostname by calling * the code provided by iSECPartners. Note that even though * the "Everything You've Always Wanted to Know About * Certificate Validation With OpenSSL (But Were Afraid to * Ask)" paper from iSECPartners says very explicitly not to * call SSL_CTX_set_cert_verify_callback (at the bottom of * page 2), what we're doing here is safe because our * cert_verify_callback() calls X509_verify_cert(), which is * OpenSSL's built-in routine which would have been called if * we hadn't set the callback. Therefore, we're just * "wrapping" OpenSSL's routine, not replacing it. */ SSL_CTX_set_cert_verify_callback(ssl_ctx, cert_verify_callback, (void *) host); #else // _WIN32 (void)crt; #endif // _WIN32 // Create event base base = event_base_new(); if (!base) { perror("event_base_new()"); goto error; } // Create OpenSSL bufferevent and stack evhttp on top of it ssl = SSL_new(ssl_ctx); if (ssl == NULL) { err_openssl("SSL_new()"); goto error; } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME // Set hostname for SNI extension SSL_set_tlsext_host_name(ssl, host); #endif if (strcasecmp(scheme, "http") == 0) { bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE); } else { type = HTTPS; bev = bufferevent_openssl_socket_new(base, -1, ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); } if (bev == NULL) { fprintf(stderr, "bufferevent_openssl_socket_new() failed\n"); goto error; } bufferevent_openssl_set_allow_dirty_shutdown(bev, 1); // For simplicity, we let DNS resolution block. Everything else should be // asynchronous though. evcon = evhttp_connection_base_bufferevent_new(base, NULL, bev, host, port); if (evcon == NULL) { fprintf(stderr, "evhttp_connection_base_bufferevent_new() failed\n"); goto error; } if (retries > 0) { evhttp_connection_set_retries(evcon, retries); } if (timeout >= 0) { evhttp_connection_set_timeout(evcon, timeout); } // Fire off the request req = evhttp_request_new(http_request_done, bev); if (req == NULL) { fprintf(stderr, "evhttp_request_new() failed\n"); goto error; } output_headers = evhttp_request_get_output_headers(req); evhttp_add_header(output_headers, "Host", host); evhttp_add_header(output_headers, "Connection", "close"); if (data_file) { /* NOTE: In production code, you'd probably want to use * evbuffer_add_file() or evbuffer_add_file_segment(), to * avoid needless copying. */ FILE * f = fopen(data_file, "rb"); char buf[1024]; size_t s; size_t bytes = 0; if (!f) { syntax(); goto error; } output_buffer = evhttp_request_get_output_buffer(req); while ((s = fread(buf, 1, sizeof(buf), f)) > 0) { evbuffer_add(output_buffer, buf, s); bytes += s; } evutil_snprintf(buf, sizeof(buf)-1, "%lu", (unsigned long)bytes); evhttp_add_header(output_headers, "Content-Length", buf); fclose(f); } r = evhttp_make_request(evcon, req, data_file ? EVHTTP_REQ_POST : EVHTTP_REQ_GET, uri); if (r != 0) { fprintf(stderr, "evhttp_make_request() failed\n"); goto error; } event_base_dispatch(base); goto cleanup; error: ret = 1; cleanup: if (evcon) evhttp_connection_free(evcon); if (http_uri) evhttp_uri_free(http_uri); event_base_free(base); if (ssl_ctx) SSL_CTX_free(ssl_ctx); if (type == HTTP && ssl) SSL_free(ssl); #if OPENSSL_VERSION_NUMBER < 0x10100000L EVP_cleanup(); ERR_free_strings(); #ifdef EVENT__HAVE_ERR_REMOVE_THREAD_STATE ERR_remove_thread_state(NULL); #else ERR_remove_state(0); #endif CRYPTO_cleanup_all_ex_data(); sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); #endif /*OPENSSL_VERSION_NUMBER < 0x10100000L */ #ifdef _WIN32 WSACleanup(); #endif return ret; }
bool LibEventHttpClient::send(const std::string &url, const std::vector<std::string> &headers, int timeoutSeconds, bool async, const void *data /* = NULL */, int size /* = 0 */) { clear(); m_url = url; evhttp_request* request = evhttp_request_new(on_request_completed, this); // request headers bool keepalive = true; bool addHost = true; for (unsigned int i = 0; i < headers.size(); i++) { const std::string &header = headers[i]; size_t pos = header.find(':'); if (pos != std::string::npos && header[pos + 1] == ' ') { std::string name = header.substr(0, pos); if (strcasecmp(name.c_str(), "Connection") == 0) { keepalive = false; } else if (strcasecmp(name.c_str(), "Host") == 0) { addHost = false; } int ret = evhttp_add_header(request->output_headers, name.c_str(), header.c_str() + pos + 2); if (ret >= 0) { continue; } } Logger::Error("invalid request header: [%s]", header.c_str()); } if (keepalive) { evhttp_add_header(request->output_headers, "Connection", "keep-alive"); } if (addHost) { // REVIEW: libevent never sends a Host header (nor does it properly send // HTTP 400 for HTTP/1.1 requests without such a header), in blatant // violation of RFC2616; this should perhaps be fixed in the library // proper. For now, add it if it wasn't set by the caller. if (m_port == 80) { evhttp_add_header(request->output_headers, "Host", m_address.c_str()); } else { std::ostringstream ss; ss << m_address << ":" << m_port; evhttp_add_header(request->output_headers, "Host", ss.str().c_str()); } } // post data if (data && size) { evbuffer_add(request->output_buffer, data, size); } // url evhttp_cmd_type cmd = data ? EVHTTP_REQ_POST : EVHTTP_REQ_GET; // if we have a cached connection, we need to pump the event loop to clear // any "connection closed" events that may be sitting there patiently. if (m_conn) { event_base_loop(m_eventBase, EVLOOP_NONBLOCK); } // even if we had an m_conn immediately above, it may have been cleared out // by onConnectionClosed(). if (m_conn == nullptr) { m_conn = evhttp_connection_new(m_address.c_str(), m_port); evhttp_connection_set_closecb(m_conn, on_connection_closed, this); evhttp_connection_set_base(m_conn, m_eventBase); } int ret = evhttp_make_request(m_conn, request, cmd, url.c_str()); if (ret != 0) { Logger::Error("evhttp_make_request failed"); return false; } if (timeoutSeconds > 0) { struct timeval timeout; timeout.tv_sec = timeoutSeconds; timeout.tv_usec = 0; event_set(&m_eventTimeout, -1, 0, timer_callback, m_eventBase); event_base_set(m_eventBase, &m_eventTimeout); event_add(&m_eventTimeout, &timeout); } if (async) { m_thread = new AsyncFunc<LibEventHttpClient> (this, &LibEventHttpClient::sendImpl); m_thread->start(); } else { IOStatusHelper io("libevent_http", m_address.c_str(), m_port); sendImpl(); } return true; }