Exemplo n.º 1
0
void HttpError::Throw(const char* msg,HttpServerConnection& client) {
	client.dump_context(stderr);
	client.async_write("HTTP/1.0 ");
	client.async_write(msg);
	client.async_write("\r\nConnection: close\r\n\r\n");
	ThrowGracefulClose(msg);
};
Exemplo n.º 2
0
bool HttpServer::initWebSocket(HttpServerConnection& connection, HttpRequest& request, HttpResponse& response)
{
	if (!wsEnabled)
		return false;

    WebSocket *sock = new WebSocket(&connection);
    if (!sock->initialize(request, response))
        return false;

    connection.setTimeOut(USHRT_MAX); //Disable disconnection on connection idle (no rx/tx)
	connection.setDisconnectionHandler(HttpServerConnectionDelegate(&HttpServer::onCloseWebSocket, this)); // auto remove on close
	response.sendHeader(connection); // Will push header before user data

    wsocks.addElement(sock);
    if (wsConnect) wsConnect(*sock);
    if (wsCommandEnabled &&  (request.getQueryParameter(wsCommandRequestParam) == "true"))
    {
#if ENABLE_CMD_EXECUTOR
        debugf("WebSocket Commandprocessor started");
#else
        debugf("WebSocket Commandprocessor support DISABLED via ENABLE_CMD_EXECUTOR");
#endif
    	sock->enableCommand();
    }
}
Exemplo n.º 3
0
void HttpResponse::sendHeader(HttpServerConnection &connection)
{
	if (headerSent) return;

	String top = "HTTP/1.1 " + status + "\r\n";
	connection.writeString(top.c_str(), TCP_WRITE_FLAG_MORE | TCP_WRITE_FLAG_COPY);
	for (int i = 0; i < responseHeaders.count(); i++)
	{
		String write = responseHeaders.keyAt(i) + ": " + responseHeaders.valueAt(i) + "\r\n";
		connection.writeString(write.c_str(), TCP_WRITE_FLAG_MORE | TCP_WRITE_FLAG_COPY);
	}
	connection.writeString("\r\n");
	headerSent = true;
}
Exemplo n.º 4
0
void HttpServer::processWebSocketFrame(pbuf *buf, HttpServerConnection& connection)
{
	//TODO: process splitted payload
	uint8_t* data; size_t size;
	wsFrameType frameType = wsParseInputFrame((uint8_t*)buf->payload, buf->len, &data, &size);
	WebSocket* sock = getWebSocket(connection);

	if (frameType == WS_TEXT_FRAME)
	{
		String msg;
		msg.setString((char*)data, size);
		debugf("WS: %s", msg.c_str());
		if (sock && wsMessage) wsMessage(*sock, msg);
	}
	if (frameType == WS_BINARY_FRAME)
	{
		if (sock && wsMessage) wsBinary(*sock, data, size);
	}
	else if (frameType == WS_CLOSING_FRAME)
	{
		connection.close(); // it will be processed automatically in onCloseWebSocket callback
	}
	else if (frameType == WS_INCOMPLETE_FRAME || frameType == WS_ERROR_FRAME)
		debugf("WS error reading frame: %X", frameType);
	else
		debugf("WS frame type: %X", frameType);
}
Exemplo n.º 5
0
bool HttpResponse::sendBody(HttpServerConnection &connection)
{
	if (!headerSent) sendHeader(connection);
	if (stream == NULL) return true;

	connection.write(stream);

	if (stream->isFinished())
	{
		connection.flush();
		bodySent = true;
		debugf("Stream completed");
		delete stream; // Free memory now!
		stream = NULL;
		return true;
	}
	else
		return false;
}
Exemplo n.º 6
0
bool HttpServer::initWebSocket(HttpServerConnection& connection, HttpRequest& request, HttpResponse& response)
{
	if (!wsEnabled)
		return false;

	auto sock = WebSocket(&connection);
	if (!sock.initialize(request, response))
		return false;

	connection.setDisconnectionHandler(HttpServerConnectionDelegate(&HttpServer::onCloseWebSocket, this)); // auto remove on close
	response.sendHeader(connection); // Will push header before user data

	wsocks.add(sock);
	if (wsConnect) wsConnect(sock);

	return true;
}
Exemplo n.º 7
0
void HttpServer::processWebSocketFrame(pbuf *buf, HttpServerConnection& connection)
{
	//TODO: process splitted payload
	uint8_t* data; size_t size;

	wsFrameType frameType = (wsFrameType) 0x01;
	uint8_t payloadFieldExtraBytes = 0;
	size_t payloadLength = 0;
	size_t payloadShift = 0;
	do
	{
	payloadLength = getPayloadLength((uint8_t*)buf->payload + payloadShift, buf->len, &payloadFieldExtraBytes, &frameType);

//    debugf("payloadLength: %u, payLoadShift: %u, payloadFieldExtraBytes: %u\n", payloadLength, payloadShift, payloadFieldExtraBytes);

	wsFrameType frameType = wsParseInputFrame((uint8_t*)buf->payload + payloadShift, (payloadLength + 6 + payloadFieldExtraBytes), &data, &size);
	WebSocket* sock = getWebSocket(connection);

	if (frameType == WS_TEXT_FRAME)
	{
		String msg;
		msg.setString((char*)data, size);
		debugf("WS: %s", msg.c_str());
		if (sock && wsMessage) wsMessage(*sock, msg);
#if ENABLE_CMD_EXECUTOR
		if (sock && sock->commandExecutor) sock->commandExecutor->executorReceive(msg+"\r");
#endif
	}
	else if (frameType == WS_BINARY_FRAME)
	{
		if (sock && wsMessage) wsBinary(*sock, data, size);
	}
	else if (frameType == WS_CLOSING_FRAME)
	{
		connection.close(); // it will be processed automatically in onCloseWebSocket callback
	}
	else if (frameType == WS_INCOMPLETE_FRAME || frameType == WS_ERROR_FRAME)
		debugf("WS error reading frame: %X", frameType);
	else
		debugf("WS frame type: %X", frameType);

	payloadShift += payloadLength + 6 + payloadFieldExtraBytes;
	}
	while (buf->len > payloadShift);
}
Exemplo n.º 8
0
bool EventsHandler::HandleRequest(
	AsioTlsStream& stream,
	const ApiUser::Ptr& user,
	boost::beast::http::request<boost::beast::http::string_body>& request,
	const Url::Ptr& url,
	boost::beast::http::response<boost::beast::http::string_body>& response,
	const Dictionary::Ptr& params,
	boost::asio::yield_context& yc,
	HttpServerConnection& server
)
{
	namespace asio = boost::asio;
	namespace http = boost::beast::http;

	if (url->GetPath().size() != 2)
		return false;

	if (request.method() != http::verb::post)
		return false;

	if (request.version() == 10) {
		HttpUtility::SendJsonError(response, params, 400, "HTTP/1.0 not supported for event streams.");
		return true;
	}

	Array::Ptr types = params->Get("types");

	if (!types) {
		HttpUtility::SendJsonError(response, params, 400, "'types' query parameter is required.");
		return true;
	}

	{
		ObjectLock olock(types);
		for (const String& type : types) {
			FilterUtility::CheckPermission(user, "events/" + type);
		}
	}

	String queueName = HttpUtility::GetLastParameter(params, "queue");

	if (queueName.IsEmpty()) {
		HttpUtility::SendJsonError(response, params, 400, "'queue' query parameter is required.");
		return true;
	}

	std::set<EventType> eventTypes;

	{
		ObjectLock olock(types);
		for (const String& type : types) {
			auto typeId (l_EventTypes.find(type));

			if (typeId != l_EventTypes.end()) {
				eventTypes.emplace(typeId->second);
			}
		}
	}

	EventsSubscriber subscriber (std::move(eventTypes), HttpUtility::GetLastParameter(params, "filter"), l_ApiQuery);

	server.StartStreaming();

	response.result(http::status::ok);
	response.set(http::field::content_type, "application/json");

	IoBoundWorkSlot dontLockTheIoThread (yc);

	http::async_write(stream, response, yc);
	stream.async_flush(yc);

	asio::const_buffer newLine ("\n", 1);

	for (;;) {
		auto event (subscriber.GetInbox()->Shift(yc));

		if (event) {
			CpuBoundWork buildingResponse (yc);

			String body = JsonEncode(event);

			boost::algorithm::replace_all(body, "\n", "");

			asio::const_buffer payload (body.CStr(), body.GetLength());

			buildingResponse.Done();

			asio::async_write(stream, payload, yc);
			asio::async_write(stream, newLine, yc);
			stream.async_flush(yc);
		} else if (server.Disconnected()) {
			return true;
		}
	}
}