void LibEventServer::onResponse(int worker, evhttp_request *request, int code, LibEventTransport *transport) { int nwritten = 0; bool skip_sync = false; if (request->evcon == nullptr) { evhttp_request_free(request); return; } #ifdef _EVENT_USE_OPENSSL skip_sync = evhttp_is_connection_ssl(request->evcon); #endif int totalSize = 0; if (RuntimeOption::LibEventSyncSend && !skip_sync) { const char *reason = HttpProtocol::GetReasonString(code); timespec begin, end; Timer::GetMonotonicTime(begin); #ifdef EVHTTP_SYNC_SEND_REPORT_TOTAL_LEN nwritten = evhttp_send_reply_sync(request, code, reason, nullptr, &totalSize); #else nwritten = evhttp_send_reply_sync_begin(request, code, reason, nullptr); #endif Timer::GetMonotonicTime(end); int64_t delay = gettime_diff_us(begin, end); transport->onFlushBegin(totalSize); transport->onFlushProgress(nwritten, delay); } m_responseQueue.enqueue(worker, request, code, nwritten); }
LibEventTransportTraits::LibEventTransportTraits(LibEventJobPtr job, void *opaque, int id) : server_((LibEventServer*)opaque), request_(job->request), transport_(server_, request_, id) { #ifdef _EVENT_USE_OPENSSL if (evhttp_is_connection_ssl(request_->evcon)) { transport_.setSSL(); } #endif }
void LibEventWorker::doJobImpl(LibEventJobPtr job, bool abort) { job->stopTimer(); evhttp_request *request = job->request; assert(m_opaque); LibEventServer *server = (LibEventServer*)m_opaque; LibEventTransport transport(server, request, m_id); #ifdef _EVENT_USE_OPENSSL if (evhttp_is_connection_ssl(job->request->evcon)) { transport.setSSL(); } #endif bool error = true; std::string errorMsg; if (abort) { transport.sendString("Service Unavailable", 503); return; } try { std::string cmd = transport.getCommand(); cmd = std::string("/") + cmd; if (server->shouldHandle(cmd)) { transport.onRequestStart(job->getStartTimer()); m_handler->handleRequest(&transport); error = false; } else { transport.sendString("Not Found", 404); return; } } catch (Exception &e) { if (Server::StackTraceOnError) { errorMsg = e.what(); } else { errorMsg = e.getMessage(); } } catch (std::exception &e) { errorMsg = e.what(); } catch (...) { errorMsg = "(unknown exception)"; } if (error) { if (RuntimeOption::ServerErrorMessage) { transport.sendString(errorMsg, 500); } else { transport.sendString(RuntimeOption::FatalErrorMessage, 500); } } }
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); } } }
void LibEventServer::onResponse(int worker, evhttp_request *request, int code) { int nwritten = 0; bool skip_sync = false; #ifdef _EVENT_USE_OPENSSL skip_sync = evhttp_is_connection_ssl(request->evcon); #endif if (RuntimeOption::LibEventSyncSend && !skip_sync) { const char *reason = HttpProtocol::GetReasonString(code); nwritten = evhttp_send_reply_sync_begin(request, code, reason, NULL); } m_responseQueue.enqueue(worker, request, code, nwritten); }