Commit 927579d0 authored by Hubert Denkmair's avatar Hubert Denkmair

port to uWebSockets

parent cc829b68
......@@ -4,3 +4,7 @@
[submodule "lib/msgpack-c"]
path = lib/msgpack-c
url = https://github.com/msgpack/msgpack-c.git
[submodule "lib/uWebSockets"]
path = lib/uWebSockets
url = git@git.bingo-ev.de:GPN18Programmierspiel/uWebSockets.git
branch = cmake
......@@ -2,4 +2,5 @@ cmake_minimum_required (VERSION 3.2)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "-Wall -pedantic")
add_subdirectory(lib/TcpServer/TcpServer)
add_subdirectory(lib/uWebSockets)
add_subdirectory(relayserver)
uWebSockets @ 3322671f
Subproject commit 3322671f50d0ae902a3e22708e4c98d475893961
......@@ -6,8 +6,8 @@ include_directories(${EIGEN3_INCLUDE_DIR})
include_directories(
${PROJECT_NAME}
lib/msgpack-c/include/
lib/TcpServer/TcpServer/include/
../lib/uWebSockets/src
../lib/msgpack-c/include/
)
add_executable(
......@@ -22,4 +22,9 @@ add_executable(
target_link_libraries(
${PROJECT_NAME}
tcpserver
uWebSockets
pthread
ssl
crypto
z
)
#include "RelayServer.h"
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <TcpServer/TcpSocket.h>
#include <TcpServer/EPoll.h>
#include <msgpack.hpp>
RelayServer::RelayServer()
{
_tcpServer.AddConnectionEstablishedListener(
[this](TcpSocket& socket)
{
return OnConnectionEstablished(socket);
}
);
_tcpServer.AddConnectionClosedListener(
[this](TcpSocket& socket)
{
return OnConnectionClosed(socket);
}
);
_tcpServer.AddDataAvailableListener(
[this](TcpSocket& socket)
{
return OnDataAvailable(socket);
}
);
_tcpProtocol.SetFrameCompleteCallback(
[this](uint64_t frame_id)
{
//std::cout << "frame " << frame_id << " complete." << std::endl;
for (auto& it: _connections)
{
it.second.FrameComplete(frame_id, _tcpProtocol);
}
}
);
_websocketServer.clear_access_channels(websocketpp::log::alevel::all);
_websocketServer.set_access_channels(websocketpp::log::alevel::connect);
_websocketServer.set_access_channels(websocketpp::log::alevel::disconnect);
_websocketServer.set_access_channels(websocketpp::log::alevel::app);
// websocketServer.set_message_handler()...
}
int RelayServer::Run()
{
uWS::Hub h;
EPoll epoll;
if(!_tcpServer.Listen(9009))
{
return -1;
}
epoll.AddFileDescriptor(_tcpServer.GetEPoll().GetFileDescriptor(), EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLRDHUP|EPOLLHUP);
_clientSocket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv_addr;
......@@ -69,96 +21,68 @@ int RelayServer::Run()
perror("connect to server failed");
return -1;
}
epoll.AddFileDescriptor(_clientSocket, EPOLLIN|EPOLLPRI|EPOLLERR);
while(true)
{
epoll.Poll(1000,
[this](const epoll_event& ev)
{
if (ev.data.fd == _clientSocket)
{
return _tcpProtocol.Read(_clientSocket);
}
else
_tcpProtocol.SetFrameCompleteCallback(
[this, &h](uint64_t frame_id)
{
h.getDefaultGroup<uWS::SERVER>().forEach(
[this, frame_id](uWS::WebSocket<uWS::SERVER>* sock)
{
_tcpServer.Poll(0);
auto con = static_cast<WebsocketConnection*>(sock->getUserData());
con->FrameComplete(frame_id, _tcpProtocol);
}
return true;
}
);
}
}
);
std::cout << "frame " << frame_id << " complete." << std::endl;
}
);
epoll.AddFileDescriptor(_clientSocket, EPOLLIN|EPOLLPRI|EPOLLERR);
bool RelayServer::OnConnectionEstablished(TcpSocket &socket)
{
std::cerr << "connection established to " << socket.GetPeer() << std::endl;
auto con = _websocketServer.get_connection();
con->set_write_handler(
[&socket](websocketpp::connection_hdl, char const* data, size_t size)
h.onConnection(
[](uWS::WebSocket<uWS::SERVER> *ws, uWS::HttpRequest req)
{
if (socket.Write(data, size, false) != static_cast<ssize_t>(size))
{
return websocketpp::transport::iostream::error::make_error_code(
websocketpp::transport::iostream::error::general
);
}
return websocketpp::lib::error_code();
ws->setUserData(new WebsocketConnection(ws));
}
);
con->set_shutdown_handler(
[&socket](websocketpp::connection_hdl)
h.onDisconnection(
[](uWS::WebSocket<uWS::SERVER> *ws, int code, const char *message, size_t length)
{
socket.Close();
return websocketpp::lib::error_code();
auto *con = static_cast<WebsocketConnection*>(ws->getUserData());
delete con;
}
);
con->start();
_connections.emplace(socket.GetFileDescriptor(), WebsocketConnection { socket.GetFileDescriptor(), con });
return true;
}
bool RelayServer::OnConnectionClosed(TcpSocket &socket)
{
std::cerr << "connection to " << socket.GetPeer() << " closed." << std::endl;
auto it = _connections.find(socket.GetFileDescriptor());
if (it == _connections.end())
h.onMessage([](uWS::WebSocket<uWS::SERVER> *ws, char *message, size_t length, uWS::OpCode opCode)
{
return false;
}
it->second.Eof();
_connections.erase(socket.GetFileDescriptor());
return true;
}
//ws->send(message, length, opCode);
});
bool RelayServer::OnDataAvailable(TcpSocket &socket)
{
auto it = _connections.find(socket.GetFileDescriptor());
if (it == _connections.end())
std::string response = "Hello!";
h.onHttpRequest([&](uWS::HttpResponse *res, uWS::HttpRequest req, char *data, size_t length, size_t remainingBytes)
{
return false;
}
res->end(response.data(), response.length());
});
char data[1024];
ssize_t count = socket.Read(data, sizeof(data));
if (count > 0)
if (!h.listen(9009))
{
it->second.DataReceived(data, static_cast<size_t>(count));
return -1;
}
return true;
}
bool RelayServer::OnServerDataReceived(const epoll_event &ev)
{
std::array<char, 102400> buf;
if (read(_clientSocket, buf.data(), buf.size()) <= 0)
epoll.AddFileDescriptor(h.getLoop()->getEpollFd(), EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLRDHUP|EPOLLHUP); // TODO check which events are neccessary
while (true)
{
return false;
epoll.Poll(1000,
[this, &h](const epoll_event& ev)
{
if (ev.data.fd == _clientSocket)
{
return _tcpProtocol.Read(_clientSocket);
}
else
{
h.poll();
}
return true;
}
);
}
return true;
}
#pragma once
#include <map>
#include <TcpServer/TcpServer.h>
#include <websocketpp/config/core.hpp>
#include <websocketpp/server.hpp>
#include <uWS.h>
#include "TcpProtocol.h"
#include "WebsocketConnection.h"
......@@ -12,19 +9,7 @@ class RelayServer
public:
RelayServer();
int Run();
private:
int _clientSocket;
TcpServer _tcpServer;
TcpProtocol _tcpProtocol;
typedef websocketpp::server<websocketpp::config::core> WebsocketServer;
WebsocketServer _websocketServer;
std::map<int, WebsocketConnection> _connections;
bool OnConnectionEstablished(TcpSocket &socket);
bool OnConnectionClosed(TcpSocket &socket);
bool OnDataAvailable(TcpSocket &socket);
bool OnServerDataReceived(const epoll_event& ev);
};
......@@ -2,32 +2,22 @@
#include "TcpProtocol.h"
#include "MsgPackProtocol.h"
WebsocketConnection::WebsocketConnection(int socket, WebsocketServer::connection_ptr websocket)
: _socket(socket), _websocket(websocket)
WebsocketConnection::WebsocketConnection(uWS::WebSocket<uWS::SERVER> *websocket)
: _websocket(websocket)
{
}
void WebsocketConnection::Eof()
{
_websocket->fatal_error();
}
void WebsocketConnection::DataReceived(const char *data, size_t count)
{
_websocket->read_all(data, count);
}
void WebsocketConnection::FrameComplete(uint64_t frame_id, const TcpProtocol &proto)
{
if (!_firstFrameSent)
{
msgpack::sbuffer buf;
msgpack::pack(buf, proto.GetGameInfo());
_websocket->send(buf.data(), buf.size());
_websocket->send(buf.data(), buf.size(), uWS::OpCode::BINARY);
buf.clear();
proto.GetWorldUpdate(buf);
_websocket->send(buf.data(), buf.size());
_websocket->send(buf.data(), buf.size(), uWS::OpCode::BINARY);
_firstFrameSent = true;
}
......@@ -35,12 +25,12 @@ void WebsocketConnection::FrameComplete(uint64_t frame_id, const TcpProtocol &pr
{
msgpack::sbuffer buf;
proto.GetFoodSpawnMessages(buf);
_websocket->send(buf.data(), buf.size());
_websocket->send(buf.data(), buf.size(), uWS::OpCode::BINARY);
buf.clear();
proto.GetFoodConsumeMessages(buf);
_websocket->send(buf.data(), buf.size());
_websocket->send(buf.data(), buf.size(), uWS::OpCode::BINARY);
buf.clear();
proto.GetFoodDecayMessages(buf);
_websocket->send(buf.data(), buf.size());
_websocket->send(buf.data(), buf.size(), uWS::OpCode::BINARY);
}
}
#pragma once
#include <websocketpp/config/core.hpp>
#include <websocketpp/server.hpp>
#include <uWS.h>
class TcpProtocol;
class WebsocketConnection
{
public:
typedef websocketpp::server<websocketpp::config::core> WebsocketServer;
WebsocketConnection(int socket, WebsocketServer::connection_ptr websocket);
void Eof();
void DataReceived(const char *data, size_t count);
WebsocketConnection(uWS::WebSocket<uWS::SERVER> *websocket);
void FrameComplete(uint64_t frame_id, const TcpProtocol& proto);
private:
int _socket;
WebsocketServer::connection_ptr _websocket;
uWS::WebSocket<uWS::SERVER> *_websocket;
bool _firstFrameSent = false;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment