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(); } }
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::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(); } }
/* * Start reply to client * @param [Fixnum] code HTTP code * @param [String] reason (optional) response descriptor * @return [nil] */ static VALUE t_send_reply_start(VALUE self, VALUE code, VALUE reason) { Libevent_HttpRequest *http_request; Data_Get_Struct(self, Libevent_HttpRequest, http_request); Check_Type(code, T_FIXNUM); evhttp_send_reply_start(http_request->ev_request, FIX2INT(code), reason == Qnil ? NULL : RSTRING_PTR(reason)); return Qnil; }
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); }
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; }
void HTTPHandler::info_handle(struct evhttp_request *req, void *arg) { if (evhttp_request_get_command(req) != EVHTTP_REQ_GET) return; LOG(INFO) << "Request for server infomation."; // TODO(binfei): need memory pool struct evbuffer *databuf = evbuffer_new(); evbuffer_add_printf(databuf, "hello world"); evhttp_send_reply_start(req, 200, "OK"); evhttp_send_reply_chunk(req, databuf); evhttp_send_reply_end(req); evbuffer_free(databuf); }
//----------------------------------------------------------------------------- void HTTPHandler::admin_handle(struct evhttp_request *req, void *arg) { //TODO(binfei): need ssl and sepecial command to do admin privilege LOG(INFO) << "Request for server admin."; // TODO(binfei): need memory pool struct evbuffer *databuf = evbuffer_new(); evbuffer_add_printf(databuf, "Server will be stoped."); evhttp_send_reply_start(req, 200, "OK"); evhttp_send_reply_chunk(req, databuf); evhttp_send_reply_end(req); evbuffer_free(databuf); HTTPServer *server = static_cast<HTTPServer*>(arg); server->Stop(); }
void PendingResponseQueue::process() { // clean up the pipe for next signals char buf[512]; if (read(m_ready.getOut(), buf, sizeof(buf)) < 0) { // an error occured but nothing we can really do } // making a copy so we don't hold up the mutex very long ResponsePtrVec responses; for (int i = 0; i < RuntimeOption::ResponseQueueCount; i++) { ResponseQueue &q = *m_responseQueues[i]; Lock lock(q.m_mutex); responses.insert(responses.end(), q.m_responses.begin(), q.m_responses.end()); q.m_responses.clear(); } for (unsigned int i = 0; i < responses.size(); i++) { Response &res = *responses[i]; evhttp_request *request = res.request; int code = res.code; if (request->evcon == nullptr) { evhttp_request_free(request); continue; } bool skip_sync = false; #ifdef _EVENT_USE_OPENSSL skip_sync = evhttp_is_connection_ssl(request->evcon); #endif if (res.chunked) { if (res.chunk) { if (res.firstChunk) { const char *reason = HttpProtocol::GetReasonString(code); evhttp_send_reply_start(request, code, reason); } evhttp_send_reply_chunk(request, res.chunk); } else { evhttp_send_reply_end(request); } } else if (RuntimeOption::LibEventSyncSend && !skip_sync) { evhttp_send_reply_sync_end(res.nwritten, request); } else { const char *reason = HttpProtocol::GetReasonString(code); evhttp_send_reply(request, code, reason, nullptr); } } }
/* * Send reply to client * @param [Fixnum] code HTTP code * @param [Hash] headers hash of http output headers * @param [Object] body object that response to each method that returns strings * @return [nil] */ static VALUE t_send_reply(VALUE self, VALUE code, VALUE headers, VALUE body) { Libevent_HttpRequest *http_request; Data_Get_Struct(self, Libevent_HttpRequest, http_request); Check_Type(code, T_FIXNUM); Check_Type(headers, T_HASH); t_set_output_headers(self, headers); evhttp_send_reply_start(http_request->ev_request, FIX2INT(code), NULL); rb_iterate(rb_each, body, t_send_chunk, self); evhttp_send_reply_end(http_request->ev_request); return Qnil; }
//----------------------------------------------------------------------------- bool HTTPHandler::handle(HTTPRequest *req, HTTPResponse *resp) { //call callback functions if (func_ == NULL || req == NULL || resp == NULL) return false; //prepare header, check if long or short connection const char* value = req->FindHeaders(connection_key); if (value != NULL && strncmp(connection_value, value, strlen(connection_value)) == 0) evhttp_add_header(resp->req_->output_headers, connection_key, connection_value); evhttp_send_reply_start(resp->req_, HTTP_OK, "OK"); (*func_)(req, resp, boost::bind(&HTTPHandler::finish, this, _1, req, resp)); return true; }
static void http_chunked_cb(struct evhttp_request *req, void *arg) { struct timeval when = { 0, 0 }; struct chunk_req_state *state = malloc(sizeof(struct chunk_req_state)); event_debug(("%s: called\n", __func__)); memset(state, 0, sizeof(struct chunk_req_state)); state->req = req; /* generate a chunked reply */ evhttp_send_reply_start(req, HTTP_OK, "Everything is fine"); /* but trickle it across several iterations to ensure we're not * assuming it comes all at once */ event_once(-1, EV_TIMEOUT, http_chunked_trickle_cb, state, &when); }
void PendingResponseQueue::process() { // clean up the pipe for next signals char buf[512]; read(m_ready.getOut(), buf, sizeof(buf)); // making a copy so we don't hold up the mutex very long ResponsePtrVec responses; for (int i = 0; i < RuntimeOption::ResponseQueueCount; i++) { ResponseQueue &q = *m_responseQueues[i]; Lock lock(q.m_mutex); responses.insert(responses.end(),q.m_responses.begin(),q.m_responses.end()); q.m_responses.clear(); } for (unsigned int i = 0; i < responses.size(); i++) { Response &res = *responses[i]; evhttp_request *request = res.request; int code = res.code; if (res.chunked) { if (res.chunk) { if (res.firstChunk) { const char *reason = HttpProtocol::GetReasonString(code); evhttp_send_reply_start(request, code, reason); } evhttp_send_reply_chunk(request, res.chunk); } else { evhttp_send_reply_end(request); } } else if (RuntimeOption::LibEventSyncSend) { evhttp_send_reply_sync_end(res.nwritten, request); } else { const char *reason = HttpProtocol::GetReasonString(code); evhttp_send_reply(request, code, reason, NULL); } } }
static void http_handle_req(struct evhttp_request *req, lp_type longpoll, bool *req_valid) { const char *clen_str; char *body_str; char username[65] = ""; void *body, *reply = NULL; int clen = 0; unsigned int reply_len = 0; json_t *jreq; json_error_t jerr; bool rc; struct evbuffer *evbuf; if (!http_get_username(req, username, req->chunked)) return; if (longpoll == LP_NONE) { clen_str = evhttp_find_header(req->input_headers, "Content-Length"); if (clen_str) clen = atoi(clen_str); if (clen < 1 || clen > 999999) { reqlog(req->remote_host, username, req->uri); goto err_out_bad_req; } if (EVBUFFER_LENGTH(req->input_buffer) != clen) goto err_out_bad_req; body = EVBUFFER_DATA(req->input_buffer); body_str = strndup(body, clen); if (!body_str) goto err_out_bad_req; } else if (longpoll == LP_REPLY) { body_str = strdup("{\"method\":\"getwork\",\"params\":[],\"id\":1}"); } else if (longpoll == LP_KEEPALIVE || longpoll == LP_CLOSE) { reply = malloc(sizeof(char) * 2); if (!reply) goto err_out_bad_req; reply_len = snprintf(reply, 2, " "); } if (!reply) { jreq = JSON_LOADS(body_str, &jerr); free(body_str); if (!jreq) goto err_out_bad_req; rc = msg_json_rpc(req, jreq, username, &reply, &reply_len); json_decref(jreq); if (!rc) goto err_out_bad_req; } evbuf = evbuffer_new(); if (!evbuf) { free(reply); goto err_out_bad_req; } if (evbuffer_add(evbuf, reply, reply_len)) { evbuffer_free(evbuf); free(reply); goto err_out_bad_req; } free(reply); /* req_valid is a pointer to the valid member of the list struct * containing the LP request. When the connection drops and * http_lp_close_cb is called, this bool is set to false. Because we * have the reference, we can check before each send command if the * close callback has been called or if the request is still OK. * * We only have to check this when sending chunked, because if we send * in one go, there is nothing that could have closed the request, as * we're single threaded. For now. */ if (longpoll == LP_NONE) { /* Send normal requests not chunked */ evhttp_send_reply(req, HTTP_OK, "ok", evbuf); } else { if (!req->chunked && is_valid(req_valid)) evhttp_send_reply_start(req, HTTP_OK, "ok"); if (is_valid(req_valid)) evhttp_send_reply_chunk(req, evbuf); if (longpoll != LP_KEEPALIVE && is_valid(req_valid)) evhttp_send_reply_end(req); } evbuffer_free(evbuf); return; err_out_bad_req: /* When we've already sent headers, we can't really give an error so * we just send an empty reply... */ if (req->chunked) { if (is_valid(req_valid)) evhttp_send_reply_end(req); } else { evhttp_send_reply(req, HTTP_BADREQUEST, "invalid args", NULL); } }
/* 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); }
static void HHVM_METHOD(EventHttpRequest, sendReplyStart, int64_t code, const String &reason) { EventHttpRequestResourceData *event_http_request_resource_data = FETCH_RESOURCE(this_, EventHttpRequestResourceData, s_event_http_request); evhttp_send_reply_start((evhttp_request_t *) event_http_request_resource_data->getInternalResourceData(), code, reason.c_str()); }
void handle_http_static(struct evhttp_request *req, void *arg){ global_data * global = (global_data *) arg; struct evkeyvalq options; evhttp_parse_query(req->uri, &options); char filename[1000]; filename[0] = '\0'; strcat(filename, global->static_source); //make sure it ends in / at this point if(filename[strlen(filename)-1] != '/') strcat(filename, "/"); char * start = req->uri; if(*start == '/') ++start; char * ptr = start; //look for the end of the string, end of the uri, or .. while(*ptr != '\0' && *ptr != '?' && !(*ptr == '.' && *(ptr+1) == '.')) ++ptr; if(*ptr == '\0'){ strncat(filename, start, 1000 - (ptr - start) - strlen(filename)); }else if(*ptr == '?'){ strncat(filename, start, (ptr - start < (unsigned int)(1000 - strlen(filename)) ? ptr - start : 1000 - strlen(filename)) ); } //if it included .. , just ignore the url altogether //add index.html if it ends in / at this point if(filename[strlen(filename)-1] == '/') strcat(filename, "index.html"); FILE *fd; char buf[4096]; if((fd = fopen(filename, "r")) == NULL){ struct evbuffer *evb; evb = evbuffer_new(); evbuffer_add_printf(evb, "File Not found: %s\n", req->uri); evhttp_send_reply(req, HTTP_NOTFOUND, "Not Found", evb); evbuffer_free(evb); }else{ evhttp_send_reply_start(req, HTTP_OK, "OK"); int len; struct evbuffer *evb; while((len = fread(buf, sizeof(char), 4096, fd))){ evb = evbuffer_new(); evbuffer_add(evb, buf, len); evhttp_send_reply_chunk(req, evb); evbuffer_free(evb); } evhttp_send_reply_end(req); fclose(fd); } evhttp_clear_headers(&options); }