void Transport::sendRawLocked(void *data, int size, int code /* = 200 */, bool compressed /* = false */, bool chunked /* = false */, const char *codeInfo /* = "" */ ) { if (!compressed && RuntimeOption::ForceChunkedEncoding) { chunked = true; } if (m_chunkedEncoding) { chunked = true; assert(!compressed); } else if (chunked) { m_chunkedEncoding = true; assert(!compressed); } // I don't think there is any need to send an empty chunk, other than sending // out headers earlier, which seems to be a useless feature. if (chunked && size == 0) { return; } if (!m_headerCallbackDone && !m_headerCallback.isNull()) { // We could use m_headerSent here, however it seems we can still // end up in an infinite loop when: // m_headerCallback calls flush() // flush() triggers php's recursion guard // the recursion guard calls back into m_headerCallback m_headerCallbackDone = true; vm_call_user_func(m_headerCallback, null_array); } // compression handling ServerStatsHelper ssh("send"); String response = prepareResponse(data, size, compressed, !chunked); if (m_responseCode < 0) { m_responseCode = code; m_responseCodeInfo = codeInfo ? codeInfo: ""; } // HTTP header handling if (!m_headerSent) { String orig_response((const char *)data, size, CopyString); prepareHeaders(compressed, chunked, response, orig_response); m_headerSent = true; } m_responseSize += response.size(); ServerStats::SetThreadMode(ServerStats::ThreadMode::Writing); sendImpl(response.data(), response.size(), m_responseCode, chunked); ServerStats::SetThreadMode(ServerStats::ThreadMode::Processing); ServerStats::LogBytes(size); if (RuntimeOption::EnableStats && RuntimeOption::EnableWebStats) { ServerStats::Log("network.uncompressed", size); ServerStats::Log("network.compressed", response.size()); } }
void Transport::onSendEnd() { if (m_compressor && m_chunkedEncoding) { bool compressed = false; String response = prepareResponse("", 0, compressed, true); sendImpl(response.data(), response.size(), m_responseCode, true); } onSendEndImpl(); }
bool DebuggerCommand::send(DebuggerThriftBuffer &thrift) { try { thrift.reset(false); sendImpl(thrift); thrift.flush(); } catch (...) { Logger::Verbose("DebuggerCommand::send(): a socket error has happened"); thrift.close(); return false; } return true; }
// Resets the buffer, serializes this command into the buffer and then // flushes the buffer. // Returns false if an exception occurs during these steps. bool DebuggerCommand::send(DebuggerThriftBuffer &thrift) { TRACE(5, "DebuggerCommand::send cmd of type %d\n", m_type); try { thrift.reset(false); sendImpl(thrift); thrift.flush(); } catch (...) { Logger::Error("DebuggerCommand::send(): a socket error has happened"); return false; } return true; }
void Transport::sendRaw(void *data, int size, int code /* = 200 */, bool compressed /* = false */, bool chunked /* = false */, const char *codeInfo /* = "" */ ) { ASSERT(data || size == 0); ASSERT(size >= 0); FiberWriteLock lock(this); if (!compressed && RuntimeOption::ForceChunkedEncoding) { chunked = true; } if (m_chunkedEncoding) { chunked = true; ASSERT(!compressed); } else if (chunked) { m_chunkedEncoding = true; ASSERT(!compressed); } // I don't think there is any need to send an empty chunk, other than sending // out headers earlier, which seems to be a useless feature. if (chunked && size == 0) { return; } // compression handling ServerStatsHelper ssh("send"); String response = prepareResponse(data, size, compressed, !chunked); if (m_responseCode < 0) { m_responseCode = code; m_responseCodeInfo = codeInfo ? codeInfo: ""; } // HTTP header handling if (!m_headerSent) { prepareHeaders(compressed, data, size); m_headerSent = true; } m_responseSize += response.size(); ServerStats::SetThreadMode(ServerStats::Writing); sendImpl(response.data(), response.size(), m_responseCode, chunked); ServerStats::SetThreadMode(ServerStats::Processing); ServerStats::LogBytes(size); if (RuntimeOption::EnableStats && RuntimeOption::EnableWebStats) { ServerStats::Log("network.uncompressed", size); ServerStats::Log("network.compressed", response.size()); } }
MojErr MojService::send(MojServiceRequest* req, const MojChar* service, const MojChar* method, Token& tokenOut) { MojAssert(req && service && method); MojAssertMutexUnlocked(m_mutex); MojLogTrace(s_log); // NOV-130089: sendImpl and addReqest must be atomic MojThreadGuard guard(m_mutex); MojErr err = sendImpl(req, service, method, tokenOut); MojErrCheck(err); err = addRequest(req); MojErrCheck(err); return MojErrNone; }
bool Connection::send( SmartPtr<PacketBase> packet, bool safe, Priority prio, unsigned channel ) { // connected? if( state()!=connectedState ) return false; // prepare packet unsigned size = packet->compiledSize()+1; char *buffer = (char*)malloc( size ); packet->compile( buffer+1 ); buffer[0]=127; // set priority PacketPriority pprio = MEDIUM_PRIORITY; switch( prio ) { case lowPriority: pprio=LOW_PRIORITY; break; case mediumPriority: pprio=MEDIUM_PRIORITY; break; case highPriority: pprio=HIGH_PRIORITY; break; default: break; } // set reliability mode PacketReliability reliability; if( safe ) reliability = RELIABLE_ORDERED; else reliability = RELIABLE_SEQUENCED; // send bool ok = sendImpl( (char*)buffer, size, pprio, reliability, channel ); // free packet buffer free( buffer ); // error? if( !ok ) { dout << "Failed to send packet." << std::endl; return false; } 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; }
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; }
typename C::result_type do_send(typename C::argument_type arg, Detail::ResultTypeIsVoid<false>) { return try_deserialize_result<typename C::result_type>(sendImpl(GetTypeName(Identity<C>()), Serialize(arg))); }
void do_send(typename C::argument_type arg, Detail::ResultTypeIsVoid<true>) { try_deserialize_result<void>(sendImpl(GetTypeName(Identity<C>()), Serialize(arg))); }
typename C::result_type do_send(Detail::ResultTypeIsVoid<false>) { return try_deserialize_result<typename C::result_type>(sendImpl(GetTypeName(Identity<C>()), "")); }
void do_send(Detail::ResultTypeIsVoid<true>) { try_deserialize_result<void>(sendImpl(GetTypeName(Identity<C>()), "")); }