Ejemplo n.º 1
0
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());
  }
}
Ejemplo n.º 2
0
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();
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
// 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;
}
Ejemplo n.º 5
0
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());
    }
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
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;

  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;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
Archivo: main.cpp Proyecto: CCJY/coliru
 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)));
 }
Ejemplo n.º 11
0
Archivo: main.cpp Proyecto: CCJY/coliru
 void do_send(typename C::argument_type arg, Detail::ResultTypeIsVoid<true>)
 {
     try_deserialize_result<void>(sendImpl(GetTypeName(Identity<C>()), Serialize(arg)));
 }
Ejemplo n.º 12
0
Archivo: main.cpp Proyecto: CCJY/coliru
 typename C::result_type do_send(Detail::ResultTypeIsVoid<false>)
 {
     return try_deserialize_result<typename C::result_type>(sendImpl(GetTypeName(Identity<C>()), ""));
 }
Ejemplo n.º 13
0
Archivo: main.cpp Proyecto: CCJY/coliru
 void do_send(Detail::ResultTypeIsVoid<true>)
 {
     try_deserialize_result<void>(sendImpl(GetTypeName(Identity<C>()), ""));
 }