void request_handler(struct evhttp_request *req, void *arg) { const char *uri; uri = evhttp_request_uri(req); if(strncmp(uri, "/updates/", 9) != 0){ evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); if (settings.verbose > 0) fprintf(stderr, "URL not found.. needs to be /updates/... but was %s\n", uri); return; } const char *rkey; struct evkeyvalq args; TAILQ_INIT(&args); evhttp_parse_query(uri, &args); rkey = evhttp_find_header(&args, "rkey"); if (NULL == rkey) { evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); if (settings.verbose > 0) fprintf(stderr, "RKey param not found in request URI %s\n", uri); evhttp_clear_headers(&args); return; } fprintf(stderr, "Using RKey: %s\n", rkey); char *cached = fetch_memcached(rkey); if (NULL == cached) { evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); fprintf(stderr, "RKey %s not found in Memcache!\n", rkey); evhttp_clear_headers(&args); return; } int uid = atoi(cached); fprintf(stderr, "Great, found RKey in Memcached: %s = %s and now UID %d\n", rkey, cached, uid); struct evbuffer *buf = evbuffer_new(); evhttp_add_header(req->output_headers, "Content-Type", "text/html; charset=UTF-8"); evhttp_add_header(req->output_headers, "Connection", "keep-alive"); evhttp_add_header(req->output_headers, "Cache-Control", "no-cache"); evhttp_send_reply_start(req, HTTP_OK, "OK"); evbuffer_add_printf(buf, "Welcome, RKey: ‘%s’\n", rkey); evhttp_send_reply_chunk(req, buf); evbuffer_free(buf); clients[uid] = req; evhttp_clear_headers(&args); free(cached); evhttp_connection_set_closecb( req->evcon, cleanup, &slots[uid] ); }
void Subscriber::close() { if(req->evcon) { evhttp_connection_set_closecb(req->evcon, NULL, NULL); } evhttp_send_reply_end(req); channel->serv->sub_end(this); }
void Subscriber::start(){ #ifndef WIN32 bufferevent_enable(req->evcon->bufev, EV_READ); #endif evhttp_connection_set_closecb(req->evcon, on_sub_disconnect, this); evhttp_add_header(req->output_headers, "Connection", "keep-alive"); evhttp_add_header(req->output_headers, "Content-Type", "text/html;charset=UTF-8"); evhttp_send_reply_start(req, HTTP_OK, "OK"); if (this->type == POLL){ } else if (this->type == IFRAME){ struct evbuffer *buf = evbuffer_new(); evbuffer_add_printf(buf, "%s\n", iframe_header.c_str()); evhttp_send_reply_chunk(this->req, buf); evbuffer_free(buf); } if (this->seq_next == 0) { this->seq_next = channel->seq_next; } if (!channel->msg_list.empty() && channel->seq_next != this->seq_next){ this->send_old_msgs(); } }
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"); }
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); }
static void stream_end(struct stream_ctx *st, int failed) { struct evhttp_connection *evcon; evcon = evhttp_request_get_connection(st->req); if (evcon) evhttp_connection_set_closecb(evcon, NULL, NULL); if (!failed) evhttp_send_reply_end(st->req); evbuffer_free(st->evbuf); event_free(st->ev); if (st->xcode) transcode_cleanup(st->xcode); else { free(st->buf); close(st->fd); } #ifdef HAVE_LIBEVENT2_OLD if (g_st == st) g_st = NULL; #endif free(st); }
void Subscriber::start(){ bufferevent_enable(req->evcon->bufev, EV_READ); evhttp_connection_set_closecb(req->evcon, on_sub_disconnect, this); evhttp_add_header(req->output_headers, "Connection", "keep-alive"); //evhttp_add_header(req->output_headers, "Cache-Control", "no-cache"); //evhttp_add_header(req->output_headers, "Expires", "0"); evhttp_add_header(req->output_headers, "Content-Type", "text/html; charset=utf-8"); evhttp_send_reply_start(req, HTTP_OK, "OK"); if(this->type == POLL){ // }else if(this->type == IFRAME){ struct evbuffer *buf = evhttp_request_get_output_buffer(this->req); evbuffer_add_printf(buf, "%s\n", iframe_header.c_str()); evhttp_send_reply_chunk(this->req, buf); } // send buffered messages if(this->seq_next == 0){ this->seq_next = channel->seq_next; } if(!channel->msg_list.empty() && channel->seq_next != this->seq_next){ this->send_old_msgs(); } }
int Server::psub_end(PresenceSubscriber *psub){ struct evhttp_request *req = psub->req; if(req->evcon){ evhttp_connection_set_closecb(req->evcon, NULL, NULL); } evhttp_send_reply_end(req); psubs.remove(psub); log_info("%s:%d psub_end, psubs: %d", req->remote_host, req->remote_port, psubs.size); return 0; }
int Server::sub(struct evhttp_request *req){ struct evkeyvalq params; const char *uri = evhttp_request_get_uri(req); evhttp_parse_query(uri, ¶ms); struct bufferevent *bev = evhttp_connection_get_bufferevent(req->evcon); bufferevent_enable(bev, EV_READ); int cid = -1; const char *cb = NULL; //const char *token = NULL; struct evkeyval *kv; for(kv = params.tqh_first; kv; kv = kv->next.tqe_next){ if(strcmp(kv->key, "id") == 0){ cid = atoi(kv->value); }else if(strcmp(kv->key, "cb") == 0){ cb = kv->value; } } if(cid < 0 || cid >= channels.size()){ evhttp_send_reply(req, 404, "Not Found", NULL); return 0; } Channel *channel = &channels[cid]; if(channel->sub_count >= MAX_SUBSCRIBERS_PER_CHANNEL){ evhttp_send_reply(req, 429, "Too Many Requests", NULL); return 0; } Subscriber *sub = sub_pool.alloc(); sub->req = req; sub->serv = this; sub->cb = cb? cb : DEFAULT_JSONP_CALLBACK; //sub->last_recv = ... channel->add_subscriber(sub); log_debug("channel: %d, add sub, sub_count: %d", channel->id, channel->sub_count); evhttp_add_header(req->output_headers, "Content-Type", "text/html; charset=utf-8"); evhttp_send_reply_start(req, HTTP_OK, "OK"); struct evbuffer *buf; buf = evbuffer_new(); evbuffer_add_printf(buf, "%s({type: \"hello\", id: \"%d\", content: \"From icomet server.\"});\n", sub->cb.c_str(), channel->id); evhttp_send_reply_chunk(req, buf); evbuffer_free(buf); evhttp_connection_set_closecb(req->evcon, on_disconnect, sub); return 0; }
void web_pipeline_stream(struct evhttp_request *req, void *arg) { struct timeval when = { 0, 20 }; struct evkeyvalq headers; const char *uri; int idx = 0; moModule *module = NULL; uri = evhttp_request_uri(req); evhttp_parse_query(uri, &headers); if ( evhttp_find_header(&headers, "objectname") == NULL ) { evhttp_clear_headers(&headers); return web_error(req, "missing objectname"); } module = module_search(evhttp_find_header(&headers, "objectname"), pipeline); if ( module == NULL ) { evhttp_clear_headers(&headers); return web_error(req, "object not found"); } if ( evhttp_find_header(&headers, "index") != NULL ) idx = atoi(evhttp_find_header(&headers, "index")); if ( idx < 0 || idx >= module->getOutputCount() ) { evhttp_clear_headers(&headers); return web_error(req, "invalid index"); } struct chunk_req_state *state = (struct chunk_req_state*)malloc(sizeof(struct chunk_req_state)); memset(state, 0, sizeof(struct chunk_req_state)); state->req = req; state->closed = false; state->stream = new otStreamModule(); state->delay = 100; if ( evhttp_find_header(&headers, "scale") != NULL ) state->stream->property("scale").set(evhttp_find_header(&headers, "scale")); if ( evhttp_find_header(&headers, "delay") != NULL ) state->delay = atoi(evhttp_find_header(&headers, "delay")); state->stream->setInput(module->getOutput(idx)); evhttp_add_header(req->output_headers, "Content-Type", "multipart/x-mixed-replace; boundary=mjpegstream"); evhttp_send_reply_start(req, HTTP_OK, "Everything is fine"); evhttp_connection_set_closecb(req->evcon, web_pipeline_stream_close, state); event_once(-1, EV_TIMEOUT, web_pipeline_stream_trickle, state, &when); }
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 Server::psub(struct evhttp_request *req){ bufferevent_enable(req->evcon->bufev, EV_READ); PresenceSubscriber *psub = new PresenceSubscriber(); psub->req = req; psub->serv = this; psubs.push_back(psub); log_info("%s:%d psub, psubs: %d", req->remote_host, req->remote_port, psubs.size); evhttp_send_reply_start(req, HTTP_OK, "OK"); evhttp_connection_set_closecb(req->evcon, on_psub_disconnect, psub); return 0; }
// create S3HttpConnection object // establish HTTP connections to S3 gpointer s3http_connection_create (Application *app) { S3HttpConnection *con; int port; AppConf *conf; con = g_new0 (S3HttpConnection, 1); if (!con) { LOG_err (CON_LOG, "Failed to create S3HttpConnection !"); return NULL; } conf = application_get_conf (app); con->app = app; con->bucket_name = g_strdup (application_get_bucket_name (app)); con->is_acquired = FALSE; port = application_get_port (app); // if no port is specified, libevent returns -1 if (port == -1) { port = conf->http_port; } LOG_debug (CON_LOG, "Connecting to %s:%d", application_get_host (app), port ); // XXX: implement SSL con->evcon = evhttp_connection_base_new ( application_get_evbase (app), application_get_dnsbase (app), application_get_host (app), port ); if (!con->evcon) { LOG_err (CON_LOG, "Failed to create evhttp_connection !"); return NULL; } evhttp_connection_set_timeout (con->evcon, conf->timeout); evhttp_connection_set_retries (con->evcon, conf->retries); evhttp_connection_set_closecb (con->evcon, s3http_connection_on_close, con); return (gpointer)con; }
void Subscriber::close(){ log_debug("subscriber close invoked"); if (req->evcon){ evhttp_connection_set_closecb(req->evcon, NULL, NULL); log_debug("evhttp_connection_set_closecb invoked"); } log_debug("before evhttp_send_reply_end"); evhttp_send_reply_end(req); log_debug("before channel->serv->sub_end(this);"); channel->serv->sub_end(this); log_debug("after channel->serv->sub_end(this);"); }
void mkhttp(runner *run) { struct evhttp_connection *evcon; evcon = evhttp_connection_new(http_hostname, http_port); if(evcon == nil) panic("evhttp_connection_new"); evhttp_connection_set_closecb(evcon, &closecb, run); /* note: we manage our own per-request timeouts, since the underlying library does not give us enough error reporting fidelity */ run->evcon = evcon; }
IoObject *IoEvConnection_connect(IoEvConnection *self, IoObject *locals, IoMessage *m) { IoEventManager *em = IoObject_getSlot_(self, IOSYMBOL("eventManager")); IoSeq *address = IoObject_seqGetSlot_(self, IOSYMBOL("address")); int port = IoObject_doubleGetSlot_(self, IOSYMBOL("port")); IOASSERT(CONN(self) == 0x0, "already have connection"); IOASSERT(ISEEVENTMANAGER(em), "eventManager slot not set properly"); //printf("IoEventManager_rawBase(em) = %p\n", (void *)IoEventManager_rawBase(em)); IoObject_setDataPointer_(self, evhttp_connection_new(CSTRING(address), port)); evhttp_connection_set_base(CONN(self), IoEventManager_rawBase(em)); evhttp_connection_set_closecb(CONN(self), IoEvConnection_ConnectionCloseCallback, self); return self; }
struct evhttp_connection * mkhttp() { struct evhttp_connection *evcon; evcon = evhttp_connection_new(http_hostname, http_port); if(evcon == nil) panic("evhttp_connection_new"); evhttp_connection_set_closecb(evcon, &closecb, nil); /* note: we manage our own per-request timeouts, since the underlying library does not give us enough error reporting fidelity */ /* also set some socket options manually. */ return(evcon); }
void EvHttpSyncClient::open(const std::string& sHost, int32_t nPort) { m_sHost = sHost; m_nPort = nPort; m_bOwnEventBase = false; if (!m_evbase) { FX_EVENT_BASE_NEW(m_evbase); m_bOwnEventBase = true; } m_pConn = evhttp_connection_base_new(m_evbase, NULL, m_sHost.c_str(), (unsigned short)m_nPort); if (!m_pConn) { FIRTEX_THROW_AND_LOG(NetworkException, "evhttp_connection_base_new FAILED"); } setTimeout(DEFAULT_TIMEOUT); setRetries(DEFAULT_MAX_RETRY); evhttp_connection_set_closecb(m_pConn, onCloseConnection, this); m_lastState = ST_OK; }
/* Thread: httpd */ void httpd_stream_file(struct evhttp_request *req, int id) { struct media_file_info *mfi; struct stream_ctx *st; void (*stream_cb)(int fd, short event, void *arg); struct stat sb; struct timeval tv; struct evhttp_connection *evcon; struct evkeyvalq *input_headers; struct evkeyvalq *output_headers; const char *param; const char *param_end; const char *ua; const char *client_codecs; char buf[64]; int64_t offset; int64_t end_offset; off_t pos; int transcode; int ret; offset = 0; end_offset = 0; input_headers = evhttp_request_get_input_headers(req); param = evhttp_find_header(input_headers, "Range"); if (param) { DPRINTF(E_DBG, L_HTTPD, "Found Range header: %s\n", param); /* Start offset */ ret = safe_atoi64(param + strlen("bytes="), &offset); if (ret < 0) { DPRINTF(E_LOG, L_HTTPD, "Invalid start offset, will stream whole file (%s)\n", param); offset = 0; } /* End offset, if any */ else { param_end = strchr(param, '-'); if (param_end && (strlen(param_end) > 1)) { ret = safe_atoi64(param_end + 1, &end_offset); if (ret < 0) { DPRINTF(E_LOG, L_HTTPD, "Invalid end offset, will stream to end of file (%s)\n", param); end_offset = 0; } if (end_offset < offset) { DPRINTF(E_LOG, L_HTTPD, "End offset < start offset, will stream to end of file (%" PRIi64 " < %" PRIi64 ")\n", end_offset, offset); end_offset = 0; } } } } mfi = db_file_fetch_byid(id); if (!mfi) { DPRINTF(E_LOG, L_HTTPD, "Item %d not found\n", id); evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); return; } if (mfi->data_kind != DATA_KIND_FILE) { evhttp_send_error(req, 500, "Cannot stream radio station"); goto out_free_mfi; } st = (struct stream_ctx *)malloc(sizeof(struct stream_ctx)); if (!st) { DPRINTF(E_LOG, L_HTTPD, "Out of memory for struct stream_ctx\n"); evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); goto out_free_mfi; } memset(st, 0, sizeof(struct stream_ctx)); st->fd = -1; ua = evhttp_find_header(input_headers, "User-Agent"); client_codecs = evhttp_find_header(input_headers, "Accept-Codecs"); transcode = transcode_needed(ua, client_codecs, mfi->codectype); output_headers = evhttp_request_get_output_headers(req); if (transcode) { DPRINTF(E_INFO, L_HTTPD, "Preparing to transcode %s\n", mfi->path); stream_cb = stream_chunk_xcode_cb; st->xcode = transcode_setup(mfi, XCODE_PCM16_HEADER, &st->size); if (!st->xcode) { DPRINTF(E_WARN, L_HTTPD, "Transcoding setup failed, aborting streaming\n"); evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); goto out_free_st; } if (!evhttp_find_header(output_headers, "Content-Type")) evhttp_add_header(output_headers, "Content-Type", "audio/wav"); } else { /* Stream the raw file */ DPRINTF(E_INFO, L_HTTPD, "Preparing to stream %s\n", mfi->path); st->buf = (uint8_t *)malloc(STREAM_CHUNK_SIZE); if (!st->buf) { DPRINTF(E_LOG, L_HTTPD, "Out of memory for raw streaming buffer\n"); evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); goto out_free_st; } stream_cb = stream_chunk_raw_cb; st->fd = open(mfi->path, O_RDONLY); if (st->fd < 0) { DPRINTF(E_LOG, L_HTTPD, "Could not open %s: %s\n", mfi->path, strerror(errno)); evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); goto out_cleanup; } ret = stat(mfi->path, &sb); if (ret < 0) { DPRINTF(E_LOG, L_HTTPD, "Could not stat() %s: %s\n", mfi->path, strerror(errno)); evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); goto out_cleanup; } st->size = sb.st_size; pos = lseek(st->fd, offset, SEEK_SET); if (pos == (off_t) -1) { DPRINTF(E_LOG, L_HTTPD, "Could not seek into %s: %s\n", mfi->path, strerror(errno)); evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); goto out_cleanup; } st->offset = offset; st->end_offset = end_offset; /* Content-Type for video files is different than for audio files * and overrides whatever may have been set previously, like * application/x-dmap-tagged when we're speaking DAAP. */ if (mfi->has_video) { /* Front Row and others expect video/<type> */ ret = snprintf(buf, sizeof(buf), "video/%s", mfi->type); if ((ret < 0) || (ret >= sizeof(buf))) DPRINTF(E_LOG, L_HTTPD, "Content-Type too large for buffer, dropping\n"); else { evhttp_remove_header(output_headers, "Content-Type"); evhttp_add_header(output_headers, "Content-Type", buf); } } /* If no Content-Type has been set and we're streaming audio, add a proper * Content-Type for the file we're streaming. Remember DAAP streams audio * with application/x-dmap-tagged as the Content-Type (ugh!). */ else if (!evhttp_find_header(output_headers, "Content-Type") && mfi->type) { ret = snprintf(buf, sizeof(buf), "audio/%s", mfi->type); if ((ret < 0) || (ret >= sizeof(buf))) DPRINTF(E_LOG, L_HTTPD, "Content-Type too large for buffer, dropping\n"); else evhttp_add_header(output_headers, "Content-Type", buf); } } st->evbuf = evbuffer_new(); if (!st->evbuf) { DPRINTF(E_LOG, L_HTTPD, "Could not allocate an evbuffer for streaming\n"); evhttp_clear_headers(output_headers); evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); goto out_cleanup; } ret = evbuffer_expand(st->evbuf, STREAM_CHUNK_SIZE); if (ret != 0) { DPRINTF(E_LOG, L_HTTPD, "Could not expand evbuffer for streaming\n"); evhttp_clear_headers(output_headers); evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); goto out_cleanup; } st->ev = event_new(evbase_httpd, -1, EV_TIMEOUT, stream_cb, st); evutil_timerclear(&tv); if (!st->ev || (event_add(st->ev, &tv) < 0)) { DPRINTF(E_LOG, L_HTTPD, "Could not add one-shot event for streaming\n"); evhttp_clear_headers(output_headers); evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); goto out_cleanup; } st->id = mfi->id; st->start_offset = offset; st->stream_size = st->size; st->req = req; if ((offset == 0) && (end_offset == 0)) { /* If we are not decoding, send the Content-Length. We don't do * that if we are decoding because we can only guesstimate the * size in this case and the error margin is unknown and variable. */ if (!transcode) { ret = snprintf(buf, sizeof(buf), "%" PRIi64, (int64_t)st->size); if ((ret < 0) || (ret >= sizeof(buf))) DPRINTF(E_LOG, L_HTTPD, "Content-Length too large for buffer, dropping\n"); else evhttp_add_header(output_headers, "Content-Length", buf); } evhttp_send_reply_start(req, HTTP_OK, "OK"); } else { if (offset > 0) st->stream_size -= offset; if (end_offset > 0) st->stream_size -= (st->size - end_offset); DPRINTF(E_DBG, L_HTTPD, "Stream request with range %" PRIi64 "-%" PRIi64 "\n", offset, end_offset); ret = snprintf(buf, sizeof(buf), "bytes %" PRIi64 "-%" PRIi64 "/%" PRIi64, offset, (end_offset) ? end_offset : (int64_t)st->size, (int64_t)st->size); if ((ret < 0) || (ret >= sizeof(buf))) DPRINTF(E_LOG, L_HTTPD, "Content-Range too large for buffer, dropping\n"); else evhttp_add_header(output_headers, "Content-Range", buf); ret = snprintf(buf, sizeof(buf), "%" PRIi64, ((end_offset) ? end_offset + 1 : (int64_t)st->size) - offset); if ((ret < 0) || (ret >= sizeof(buf))) DPRINTF(E_LOG, L_HTTPD, "Content-Length too large for buffer, dropping\n"); else evhttp_add_header(output_headers, "Content-Length", buf); evhttp_send_reply_start(req, 206, "Partial Content"); } #ifdef HAVE_POSIX_FADVISE if (!transcode) { /* Hint the OS */ posix_fadvise(st->fd, st->start_offset, st->stream_size, POSIX_FADV_WILLNEED); posix_fadvise(st->fd, st->start_offset, st->stream_size, POSIX_FADV_SEQUENTIAL); posix_fadvise(st->fd, st->start_offset, st->stream_size, POSIX_FADV_NOREUSE); } #endif evcon = evhttp_request_get_connection(req); evhttp_connection_set_closecb(evcon, stream_fail_cb, st); DPRINTF(E_INFO, L_HTTPD, "Kicking off streaming for %s\n", mfi->path); free_mfi(mfi, 0); return; out_cleanup: if (st->evbuf) evbuffer_free(st->evbuf); if (st->xcode) transcode_cleanup(st->xcode); if (st->buf) free(st->buf); if (st->fd > 0) close(st->fd); out_free_st: free(st); out_free_mfi: free_mfi(mfi, 0); }
int cmd_run(struct server *s, struct evhttp_request *rq, const char *uri, size_t uri_len, const char *body, size_t body_len) { char *qmark = strchr(uri, '?'); char *slash; const char *p; int cmd_len; int param_count = 0, cur_param = 1, i; struct cmd *cmd; formatting_fun f_format; /* count arguments */ if(qmark) { uri_len = qmark - uri; } for(p = uri; p && p < uri + uri_len; param_count++) { p = strchr(p+1, '/'); } if(body && body_len) { /* PUT request */ param_count++; } cmd = cmd_new(rq, param_count); /* parse URI parameters */ evhttp_parse_query(uri, &cmd->uri_params); /* get output formatting function */ uri_len = cmd_select_format(cmd, uri, uri_len, &f_format); /* check if we only have one command or more. */ slash = memchr(uri, '/', uri_len); if(slash) { cmd_len = slash - uri; } else { cmd_len = uri_len; } /* there is always a first parameter, it's the command name */ cmd->argv[0] = uri; cmd->argv_len[0] = cmd_len; /* check that the client is able to run this command */ if(!acl_allow_command(cmd, s->cfg, rq)) { return -1; } /* check if we have to split the connection */ if(cmd_is_subscribe(cmd)) { struct pubsub_client *ps; ps = calloc(1, sizeof(struct pubsub_client)); ps->s = s = server_copy(s); ps->cmd = cmd; ps->rq = rq; evhttp_connection_set_closecb(rq->evcon, on_http_disconnect, ps); } /* no args (e.g. INFO command) */ if(!slash) { redisAsyncCommandArgv(s->ac, f_format, cmd, 1, cmd->argv, cmd->argv_len); return 0; } p = slash + 1; while(p < uri + uri_len) { const char *arg = p; int arg_len; char *next = strchr(arg, '/'); if(!next || next > uri + uri_len) { /* last argument */ p = uri + uri_len; arg_len = p - arg; } else { /* found a slash */ arg_len = next - arg; p = next + 1; } /* record argument */ cmd->argv[cur_param] = decode_uri(arg, arg_len, &cmd->argv_len[cur_param], 1); cur_param++; } if(body && body_len) { /* PUT request */ cmd->argv[cur_param] = body; cmd->argv_len[cur_param] = body_len; } /* push command to Redis. */ redisAsyncCommandArgv(s->ac, f_format, cmd, cmd->count, cmd->argv, cmd->argv_len); for(i = 1; i < cur_param; ++i) { free((char*)cmd->argv[i]); } return 0; }
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; if (m_conn == NULL) { 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); } m_request = evhttp_request_new(on_request_completed, this); // REVIEW: libevent never sends a Host header (nor does it properly send HTTP // 400 for HTTP/1.1 requests without such a header), in blatent violation of // RFC2616; this should perhaps be fixed in the library proper. if (m_port == 80) { evhttp_add_header(m_request->output_headers, "Host", m_address.c_str()); } else { std::ostringstream ss; ss << m_address << ":" << m_port; evhttp_add_header(m_request->output_headers, "Host", ss.str().c_str()); } // request headers bool keepalive = true; for (unsigned int i = 0; i < headers.size(); i++) { const std::string &header = headers[i]; size_t pos = header.find(':'); if (pos != string::npos && header[pos + 1] == ' ') { string name = header.substr(0, pos); if (strcasecmp(name.c_str(), "Connection") == 0) { keepalive = false; } int ret = evhttp_add_header(m_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(m_request->output_headers, "Connection", "keep-alive"); } // post data if (data && size) { evbuffer_add(m_request->output_buffer, data, size); } // url evhttp_cmd_type cmd = data ? EVHTTP_REQ_POST : EVHTTP_REQ_GET; int ret = evhttp_make_request(m_conn, m_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 { sendImpl(); } return true; }
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; }