This commit is contained in:
BIAGINI Nathan committed 2023-01-15 18:57:32 +01:00
1 parent 21a839587c
commit 6f75b3b807
24 files changed
+5993 -271

No files matched your search

Vendored
BIN
View File
Binary file not shown.
+1
View File
@@ -29,6 +29,7 @@ endif()
target_compile_definitions(client PUBLIC NBN_DEBUG)
target_compile_definitions(server PUBLIC NBN_DEBUG)
target_compile_definitions(server PUBLIC NBN_RAYLIB_SERVER)
if (ENCRYPTION_ENABLED)
message("Encryption enabled")
+12 -6
View File
@@ -372,7 +372,7 @@ static int Update(void)
void DrawClient(ClientState *state, bool is_local)
{
Color color = client_colors_to_raylib_colors[state->color];
const char *text = FormatText("%.3f", state->val);
const char *text = TextFormat("%.3f", state->val);
int font_size = 20;
int text_width = MeasureText(text, font_size);
@@ -389,11 +389,11 @@ void DrawHUD(void)
unsigned int ping = stats.ping * 1000;
unsigned int packet_loss = stats.packet_loss * 100;
DrawText(FormatText("FPS: %d", GetFPS()), 450, 350, 32, MAROON);
DrawText(FormatText("Ping: %d ms", ping), 450, 400, 32, MAROON);
DrawText(FormatText("Packet loss: %d %%", packet_loss), 450, 450, 32, MAROON);
DrawText(FormatText("Upload: %.1f Bps", stats.upload_bandwidth), 450, 500, 32, MAROON);
DrawText(FormatText("Download: %.1f Bps", stats.download_bandwidth), 450, 550, 32, MAROON);
DrawText(TextFormat("FPS: %d", GetFPS()), 450, 350, 32, MAROON);
DrawText(TextFormat("Ping: %d ms", ping), 450, 400, 32, MAROON);
DrawText(TextFormat("Packet loss: %d %%", packet_loss), 450, 450, 32, MAROON);
DrawText(TextFormat("Upload: %.1f Bps", stats.upload_bandwidth), 450, 500, 32, MAROON);
DrawText(TextFormat("Download: %.1f Bps", stats.download_bandwidth), 450, 550, 32, MAROON);
}
void Draw(void)
@@ -517,6 +517,12 @@ int main(int argc, char *argv[])
SetTargetFPS(TARGET_FPS);
#endif
#ifdef __EMSCRIPTEN__
NBN_WebRTC_Register(); // Register the WebRTC driver
#else
NBN_UDP_Register(); // Register the UDP driver
#endif // __EMSCRIPTEN__
// Start the client with a protocol name (must be the same than the one used by the server), the server ip address
// and port
+8
View File
@@ -285,6 +285,14 @@ int main(int argc, char *argv[])
// Even though we do not display anything we still use raylib logging capacibilities
SetTraceLogLevel(LOG_DEBUG);
#ifdef __EMSCRIPTEN__
NBN_WebRTC_Register(); // Register the WebRTC driver
#else
NBN_UDP_Register(); // Register the UDP driver
// Register the FIFO driver (allow data to be exchanged through a FIFO)
NBN_FIFO_Register("/tmp/raylib_server-recv", "/tmp/raylib_server-send");
#endif // __EMSCRIPTEN__
// Start server with a protocol name and a port, must be done first
#ifdef EXAMPLE_ENCRYPTION
if (NBN_GameServer_Start(RAYLIB_EXAMPLE_PROTOCOL_NAME, RAYLIB_EXAMPLE_PORT, true) < 0)
+10
View File
@@ -99,8 +99,18 @@ typedef struct tagMSG *LPMSG;
#include "../../net_drivers/webrtc.h"
#else
#include "../../net_drivers/udp.h"
#endif // __EMSCRIPTEN__
#ifdef NBN_RAYLIB_SERVER
// FIFO driver only works on UNIX systems
#if defined(unix) || defined(__unix__) || defined(__unix) || \
(defined(__APPLE__) && defined(__MACH__))
#include "../../net_drivers/fifo.h"
#endif
#endif // NBN_RAYLIB_SERVER
#define TICK_RATE 60 // Simulation tick rate
// Window size, used to display window but also to cap the serialized position values within messages
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+239 -104
View File
@@ -57,6 +57,7 @@
typedef struct NBN_Endpoint NBN_Endpoint;
typedef struct NBN_Connection NBN_Connection;
typedef struct NBN_Channel NBN_Channel;
typedef struct NBN_Driver NBN_Driver;
#pragma region NBN_ConnectionVector
@@ -910,13 +911,14 @@ struct NBN_Connection
uint32_t protocol_id;
double last_recv_packet_time; /* Used to detect stale connections */
double last_flush_time; /* Last time the send queue was flushed */
double last_read_packets_time; /* Last time packets were read from the socket */
double last_read_packets_time; /* Last time packets were read from the network driver */
double time; /* Current time */
unsigned int downloaded_bytes; /* Keep track of bytes read from the socket (used for download bandwith calculation) */
uint8_t is_accepted : 1;
uint8_t is_stale : 1;
uint8_t is_closed : 1;
struct NBN_Endpoint *endpoint;
NBN_Driver *driver; /* Network driver used for that connection */
NBN_Channel *channels[NBN_MAX_CHANNELS]; /* Messages channeling (sending & receiving) */
NBN_ConnectionStats stats;
void *driver_data; /* Data attached to the connection by the underlying driver */
@@ -952,7 +954,7 @@ struct NBN_Connection
uint8_t can_encrypt : 1;
};
NBN_Connection *NBN_Connection_Create(uint32_t, uint32_t, NBN_Endpoint *, void *driver_data);
NBN_Connection *NBN_Connection_Create(uint32_t, uint32_t, NBN_Endpoint *, NBN_Driver *, void *driver_data);
void NBN_Connection_Destroy(NBN_Connection *);
int NBN_Connection_ProcessReceivedPacket(NBN_Connection *, NBN_Packet *);
int NBN_Connection_EnqueueOutgoingMessage(NBN_Connection *, NBN_Channel *, NBN_Message *);
@@ -1123,7 +1125,7 @@ void NBN_Endpoint_RegisterMessageBuilder(NBN_Endpoint *, NBN_MessageBuilder, uin
void NBN_Endpoint_RegisterMessageDestructor(NBN_Endpoint *, NBN_MessageDestructor, uint8_t);
void NBN_Endpoint_RegisterMessageSerializer(NBN_Endpoint *, NBN_MessageSerializer, uint8_t);
void NBN_Endpoint_RegisterChannel(NBN_Endpoint *, NBN_ChannelType, uint8_t);
NBN_Connection *NBN_Endpoint_CreateConnection(NBN_Endpoint *, uint32_t, void *);
NBN_Connection *NBN_Endpoint_CreateConnection(NBN_Endpoint *, uint32_t, int, void *);
int NBN_Endpoint_RegisterRPC(NBN_Endpoint *, int id, NBN_RPC_Signature, NBN_RPC_Func);
#pragma endregion /* NBN_Endpoint */
@@ -1296,7 +1298,7 @@ int NBN_GameClient_SendUnreliableMessage(NBN_OutgoingMessage *outgoing_msg);
*/
int NBN_GameClient_SendReliableMessage(NBN_OutgoingMessage *outgoing_msg);
NBN_Connection *NBN_GameClient_CreateServerConnection(void *driver_data);
NBN_Connection *NBN_GameClient_CreateServerConnection(int driver_id, void *driver_data);
/**
* Retrieve the info about the last received message.
@@ -1483,7 +1485,7 @@ void NBN_GameServer_SetContext(void *context);
*/
void *NBN_GameServer_GetContext(void);
NBN_Connection *NBN_GameServer_CreateClientConnection(uint32_t, void *);
NBN_Connection *NBN_GameServer_CreateClientConnection(uint32_t, int, void *);
/**
* Close a client's connection without a specific code (default code is -1)
@@ -1700,38 +1702,80 @@ void NBN_GameServer_Debug_RegisterCallback(NBN_ConnectionDebugCallback, void *);
#pragma region Network driver
/*
* Game client driver
*/
#define NBN_MAX_DRIVERS 4
typedef enum
{
NBN_DRIVER_GCLI_CONNECTED,
NBN_DRIVER_GCLI_SERVER_PACKET_RECEIVED
} NBN_Driver_GCli_EventType;
// Client events
NBN_DRIVER_CLI_CONNECTED,
NBN_DRIVER_CLI_PACKET_RECEIVED,
int NBN_Driver_GCli_Start(uint32_t, const char *, uint16_t);
void NBN_Driver_GCli_Stop(void);
int NBN_Driver_GCli_RecvPackets(void);
int NBN_Driver_GCli_SendPacket(NBN_Packet *);
void NBN_Driver_GCli_RaiseEvent(NBN_Driver_GCli_EventType, void *);
// Server events
NBN_DRIVER_SERV_CLIENT_CONNECTED,
NBN_DRIVER_SERV_CLIENT_PACKET_RECEIVED,
} NBN_DriverEvent;
/*
* Game server driver
*/
typedef void (*NBN_Driver_StopFunc)(void);
typedef int (*NBN_Driver_RecvPacketsFunc)(void);
typedef enum
typedef int (*NBN_Driver_ClientStartFunc)(uint32_t, const char *, uint16_t);
typedef int (*NBN_Driver_ClientSendPacketFunc)(NBN_Packet *);
typedef int (*NBN_Driver_ServerStartFunc)(uint32_t, uint16_t);
typedef int (*NBN_Driver_ServerSendPacketToFunc)(NBN_Packet *, NBN_Connection *);
typedef void (*NBN_Driver_ServerRemoveConnection)(NBN_Connection *);
typedef struct
{
NBN_DRIVER_GSERV_CLIENT_CONNECTED,
NBN_DRIVER_GSERV_CLIENT_PACKET_RECEIVED
} NBN_Driver_GServ_EventType;
/* Client functions */
NBN_Driver_ClientStartFunc cli_start;
NBN_Driver_StopFunc cli_stop;
NBN_Driver_RecvPacketsFunc cli_recv_packets;
NBN_Driver_ClientSendPacketFunc cli_send_packet;
int NBN_Driver_GServ_Start(uint32_t, uint16_t);
void NBN_Driver_GServ_Stop(void);
int NBN_Driver_GServ_RecvPackets(void);
void NBN_Driver_GServ_RemoveClientConnection(NBN_Connection *);
int NBN_Driver_GServ_SendPacketTo(NBN_Packet *, NBN_Connection *);
int NBN_Driver_GServ_RaiseEvent(NBN_Driver_GServ_EventType, void *);
/* Server functions */
NBN_Driver_ServerStartFunc serv_start;
NBN_Driver_StopFunc serv_stop;
NBN_Driver_RecvPacketsFunc serv_recv_packets;
NBN_Driver_ServerSendPacketToFunc serv_send_packet_to;
NBN_Driver_ServerRemoveConnection serv_remove_connection;
} NBN_DriverImplementation;
struct NBN_Driver
{
int id;
const char *name;
NBN_DriverImplementation impl;
};
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
static NBN_Driver nbn_drivers[NBN_MAX_DRIVERS] = {
{-1, NULL},
{-1, NULL},
{-1, NULL},
{-1, NULL}
};
#pragma clang diagnostic pop
static unsigned int nbn_driver_count = 0;
/**
* Register a new network driver, at least one network driver has to be registered.
*
* @param id ID of the driver, must be unique and within 0 and NBN_MAX_DRIVERS
* @param name Name of the driver
* @param signature Driver implementation (structure containing all driver implementation function pointers)
*/
void NBN_Driver_Register(int id, const char *name, NBN_DriverImplementation implementation);
/**
* Let nbnet know about specific network events happening within a network driver.
*
* @param ev Event type
* @param data Arbitrary data about the event
*/
int NBN_Driver_RaiseEvent(NBN_DriverEvent ev, void *data);
#pragma endregion /* Network driver */
@@ -3065,7 +3109,7 @@ static CSPRNG csprng_create();
static CSPRNG csprng_destroy(CSPRNG object);
static int csprng_get(CSPRNG, void*, unsigned long long);
NBN_Connection *NBN_Connection_Create(uint32_t id, uint32_t protocol_id, NBN_Endpoint *endpoint, void *driver_data)
NBN_Connection *NBN_Connection_Create(uint32_t id, uint32_t protocol_id, NBN_Endpoint *endpoint, NBN_Driver *driver, void *driver_data)
{
NBN_Connection *connection = (NBN_Connection*)MemoryManager_Alloc(NBN_MEM_CONNECTION);
@@ -3096,6 +3140,7 @@ NBN_Connection *NBN_Connection_Create(uint32_t id, uint32_t protocol_id, NBN_End
NBN_ConnectionStats stats = { 0 };
connection->stats = stats;
connection->driver = driver;
connection->driver_data = driver_data;
connection->can_decrypt = false;
connection->can_encrypt = false;
@@ -3566,7 +3611,7 @@ static int Connection_SendPacket(NBN_Connection *connection, NBN_Packet *packet,
if (connection->is_stale)
return 0;
return NBN_Driver_GServ_SendPacketTo(packet, connection);
return connection->driver->impl.serv_send_packet_to(packet, connection);
#endif
}
else
@@ -3574,7 +3619,9 @@ static int Connection_SendPacket(NBN_Connection *connection, NBN_Packet *packet,
#if defined(NBN_DEBUG) && defined(NBN_USE_PACKET_SIMULATOR)
return NBN_PacketSimulator_EnqueuePacket(&nbn_game_client.endpoint.packet_simulator, packet, connection);
#else
return NBN_Driver_GCli_SendPacket(packet);
NBN_Driver *driver = nbn_game_client.server_connection->driver;
return driver->impl.cli_send_packet(packet);
#endif
}
}
@@ -4458,6 +4505,8 @@ void NBN_Endpoint_Init(NBN_Endpoint *endpoint, NBN_Config config, bool is_server
void NBN_Endpoint_Deinit(NBN_Endpoint *endpoint)
{
(void)endpoint;
#if defined(NBN_DEBUG) && defined(NBN_USE_PACKET_SIMULATOR)
NBN_PacketSimulator_Stop(&endpoint->packet_simulator);
#endif
@@ -4488,10 +4537,14 @@ void NBN_Endpoint_RegisterChannel(NBN_Endpoint *endpoint, NBN_ChannelType type,
endpoint->channels[id] = type;
}
NBN_Connection *NBN_Endpoint_CreateConnection(NBN_Endpoint *endpoint, uint32_t id, void *driver_data)
NBN_Connection *NBN_Endpoint_CreateConnection(NBN_Endpoint *endpoint, uint32_t id, int driver_id, void *driver_data)
{
NBN_Driver *driver = &nbn_drivers[driver_id];
assert(driver->id >= 0);
NBN_Connection *connection = NBN_Connection_Create(
id, Endpoint_BuildProtocolId(endpoint->config.protocol_name), endpoint, driver_data);
id, Endpoint_BuildProtocolId(endpoint->config.protocol_name), endpoint, driver, driver_data);
for (int chan_id = 0; chan_id < NBN_MAX_CHANNELS; chan_id++)
{
@@ -4529,7 +4582,7 @@ int NBN_Endpoint_RegisterRPC(NBN_Endpoint *endpoint, int id, NBN_RPC_Signature s
static uint32_t Endpoint_BuildProtocolId(const char *protocol_name)
{
uint32_t protocol_id = 2166136261;
/*uint32_t protocol_id = 2166136261;
for (unsigned int i = 0; i < strlen(protocol_name); i++)
{
@@ -4537,7 +4590,8 @@ static uint32_t Endpoint_BuildProtocolId(const char *protocol_name)
protocol_id ^= protocol_name[i];
}
return protocol_id;
return protocol_id;*/
return 42;
}
static int Endpoint_ProcessReceivedPacket(NBN_Endpoint *endpoint, NBN_Packet *packet, NBN_Connection *connection)
@@ -4705,6 +4759,56 @@ static int Endpoint_SplitMessageIntoChunks(
#pragma endregion /* NBN_Endpoint */
#pragma region Network driver
static void ClientDriver_OnConnected(void);
static void ClientDriver_OnPacketReceived(NBN_Packet *packet);
static int ServerDriver_OnClientConnected(NBN_Connection *);
static int ServerDriver_OnClientPacketReceived(NBN_Packet *);
void NBN_Driver_Register(int id, const char *name, NBN_DriverImplementation implementation)
{
// driver id must be valid
assert(id >= 0 && id < NBN_MAX_DRIVERS);
NBN_Driver *driver = &nbn_drivers[id];
// driver id must be unique
assert(driver->id == -1);
driver->id = id;
driver->name = name;
driver->impl = implementation;
NBN_LogInfo("Registered driver (ID: %d, Name: %s)", id, name);
nbn_driver_count++;
}
int NBN_Driver_RaiseEvent(NBN_DriverEvent ev, void *data)
{
switch (ev)
{
case NBN_DRIVER_CLI_CONNECTED:
ClientDriver_OnConnected();
break;
case NBN_DRIVER_CLI_PACKET_RECEIVED:
ClientDriver_OnPacketReceived((NBN_Packet *)data);
break;
case NBN_DRIVER_SERV_CLIENT_CONNECTED:
return ServerDriver_OnClientConnected((NBN_Connection *)data);
case NBN_DRIVER_SERV_CLIENT_PACKET_RECEIVED:
return ServerDriver_OnClientPacketReceived((NBN_Packet *)data);
}
return 0;
}
#pragma endregion /* Network driver */
#pragma region NBN_GameClient
NBN_GameClient nbn_game_client;
@@ -4721,6 +4825,12 @@ static void GameClient_StartEncryption(void);
int NBN_GameClient_Start(const char *protocol_name, const char *ip_address, uint16_t port, bool encryption, uint8_t *connection_data)
{
if (nbn_driver_count < 1)
{
NBN_LogError("At least one network driver has to be registered");
NBN_Abort();
}
NBN_Config config = {
protocol_name,
ip_address,
@@ -4732,8 +4842,18 @@ int NBN_GameClient_Start(const char *protocol_name, const char *ip_address, uint
nbn_game_client.server_connection = NULL;
nbn_game_client.is_connected = false;
if (NBN_Driver_GCli_Start(Endpoint_BuildProtocolId(config.protocol_name), config.ip_address, config.port) < 0)
return NBN_ERROR;
for (unsigned int i = 0; i < NBN_MAX_DRIVERS; i++)
{
NBN_Driver *driver = &nbn_drivers[i];
if (driver->id < 0) continue;
if (driver->impl.cli_start(Endpoint_BuildProtocolId(config.protocol_name), config.ip_address, config.port) < 0)
{
NBN_LogError("Failed to start driver %s", driver->name);
return NBN_ERROR;
}
}
NBN_ConnectionRequestMessage *msg = NBN_ConnectionRequestMessage_Create();
@@ -4790,7 +4910,15 @@ void NBN_GameClient_Stop(void)
NBN_Connection_Destroy(nbn_game_client.server_connection);
NBN_Endpoint_Deinit(&nbn_game_client.endpoint);
NBN_Driver_GCli_Stop();
for (unsigned int i = 0; i < NBN_MAX_DRIVERS; i++)
{
NBN_Driver *driver = &nbn_drivers[i];
if (driver->id < 0) continue;
driver->impl.cli_stop();
}
NBN_LogInfo("Stopped");
}
@@ -4856,8 +4984,18 @@ int NBN_GameClient_Poll(void)
}
else
{
if (NBN_Driver_GCli_RecvPackets() < 0)
return NBN_ERROR;
for (unsigned int i = 0; i < NBN_MAX_DRIVERS; i++)
{
NBN_Driver *driver = &nbn_drivers[i];
if (driver->id < 0) continue;
if (driver->impl.cli_recv_packets() < 0)
{
NBN_LogError("Failed to read packets from driver %s", driver->name);
return NBN_ERROR;
}
}
for (unsigned int i = 0; i < NBN_MAX_CHANNELS; i++)
{
@@ -4953,9 +5091,9 @@ int NBN_GameClient_SendReliableMessage(NBN_OutgoingMessage *outgoing_msg)
return NBN_GameClient_SendMessage(outgoing_msg, NBN_CHANNEL_RESERVED_RELIABLE);
}
NBN_Connection *NBN_GameClient_CreateServerConnection(void *driver_data)
NBN_Connection *NBN_GameClient_CreateServerConnection(int driver_id, void *driver_data)
{
NBN_Connection *server_connection = NBN_Endpoint_CreateConnection(&nbn_game_client.endpoint, 0, driver_data);
NBN_Connection *server_connection = NBN_Endpoint_CreateConnection(&nbn_game_client.endpoint, 0, driver_id, driver_data);
#ifdef NBN_DEBUG
server_connection->OnMessageAddedToRecvQueue = nbn_game_client.endpoint.OnMessageAddedToRecvQueue;
@@ -5223,28 +5361,11 @@ static void GameClient_StartEncryption(void)
#pragma region Game client driver
static void Driver_GCli_OnConnected(void);
static void Driver_GCli_OnPacketReceived(NBN_Packet *packet);
void NBN_Driver_GCli_RaiseEvent(NBN_Driver_GCli_EventType ev, void *data)
{
switch (ev)
{
case NBN_DRIVER_GCLI_CONNECTED:
Driver_GCli_OnConnected();
break;
case NBN_DRIVER_GCLI_SERVER_PACKET_RECEIVED:
Driver_GCli_OnPacketReceived((NBN_Packet *)data);
break;
}
}
static void Driver_GCli_OnConnected(void)
static void ClientDriver_OnConnected(void)
{
}
static void Driver_GCli_OnPacketReceived(NBN_Packet *packet)
static void ClientDriver_OnPacketReceived(NBN_Packet *packet)
{
int ret = Endpoint_ProcessReceivedPacket(&nbn_game_client.endpoint, packet, nbn_game_client.server_connection);
@@ -5273,6 +5394,12 @@ static int GameServer_StartEncryption(NBN_Connection *);
int NBN_GameServer_Start(const char *protocol_name, uint16_t port, bool encryption)
{
if (nbn_driver_count < 1)
{
NBN_LogError("At least one network driver has to be registered");
NBN_Abort();
}
NBN_Config config = {protocol_name, NULL, port, encryption};
NBN_Endpoint_Init(&nbn_game_server.endpoint, config, true);
@@ -5284,11 +5411,17 @@ int NBN_GameServer_Start(const char *protocol_name, uint16_t port, bool encrypti
return NBN_ERROR;
}
if (NBN_Driver_GServ_Start(Endpoint_BuildProtocolId(config.protocol_name), config.port) < 0)
for (unsigned int i = 0; i < NBN_MAX_DRIVERS; i++)
{
NBN_LogError("Failed to start network driver");
NBN_Driver *driver = &nbn_drivers[i];
return NBN_ERROR;
if (driver->id < 0) continue;
if (driver->impl.serv_start(Endpoint_BuildProtocolId(config.protocol_name), config.port) < 0)
{
NBN_LogError("Failed to start driver %s", driver->name);
return NBN_ERROR;
}
}
NBN_LogInfo("Started");
@@ -5303,7 +5436,14 @@ void NBN_GameServer_Stop(void)
NBN_Endpoint_Deinit(&nbn_game_server.endpoint);
NBN_ConnectionVector_Destroy(nbn_game_server.clients);
NBN_Driver_GServ_Stop();
for (unsigned int i = 0; i < NBN_MAX_DRIVERS; i++)
{
NBN_Driver *driver = &nbn_drivers[i];
if (driver->id < 0) continue;
driver->impl.serv_stop();
}
NBN_LogInfo("Stopped");
}
@@ -5353,8 +5493,18 @@ int NBN_GameServer_Poll(void)
if (GameServer_CloseStaleClientConnections() < 0)
return NBN_ERROR;
if (NBN_Driver_GServ_RecvPackets() < 0)
return NBN_ERROR;
for (unsigned int i = 0; i < NBN_MAX_DRIVERS; i++)
{
NBN_Driver *driver = &nbn_drivers[i];
if (driver->id < 0) continue;
if (driver->impl.serv_recv_packets() < 0)
{
NBN_LogError("Failed to read packets from driver %s", driver->name);
return NBN_ERROR;
}
}
nbn_game_server.stats.download_bandwidth = 0;
@@ -5433,9 +5583,9 @@ void *NBN_GameServer_GetContext(void)
return nbn_game_server.context;
}
NBN_Connection *NBN_GameServer_CreateClientConnection(uint32_t id, void *driver_data)
NBN_Connection *NBN_GameServer_CreateClientConnection(uint32_t id, int driver_id, void *driver_data)
{
NBN_Connection *client = NBN_Endpoint_CreateConnection(&nbn_game_server.endpoint, id, driver_data);
NBN_Connection *client = NBN_Endpoint_CreateConnection(&nbn_game_server.endpoint, id, driver_id, driver_data);
#ifdef NBN_DEBUG
client->OnMessageAddedToRecvQueue = nbn_game_server.endpoint.OnMessageAddedToRecvQueue;
@@ -5814,7 +5964,7 @@ static void GameServer_RemoveClosedClientConnections(void)
{
NBN_LogDebug("Remove closed client connection (ID: %d)", client->id);
NBN_Driver_GServ_RemoveClientConnection(client);
client->driver->impl.serv_remove_connection(client);
NBN_ConnectionVector_Remove(nbn_game_server.clients, client); // actually destroying the connection should be done in user code
}
}
@@ -5927,24 +6077,7 @@ static int GameServer_HandleMessageReceivedEvent(void)
#pragma region Game server driver
static int Driver_GServ_OnClientConnected(NBN_Connection *);
static int Driver_GServ_OnClientPacketReceived(NBN_Packet *);
int NBN_Driver_GServ_RaiseEvent(NBN_Driver_GServ_EventType ev, void *data)
{
switch (ev)
{
case NBN_DRIVER_GSERV_CLIENT_CONNECTED:
return Driver_GServ_OnClientConnected((NBN_Connection *)data);
case NBN_DRIVER_GSERV_CLIENT_PACKET_RECEIVED:
return Driver_GServ_OnClientPacketReceived((NBN_Packet *)data);
}
return 0;
}
static int Driver_GServ_OnClientConnected(NBN_Connection *client)
static int ServerDriver_OnClientConnected(NBN_Connection *client)
{
if (GameServer_AddClient(client) < 0)
{
@@ -5965,7 +6098,7 @@ static int Driver_GServ_OnClientConnected(NBN_Connection *client)
return 0;
}
static int Driver_GServ_OnClientPacketReceived(NBN_Packet *packet)
static int ServerDriver_OnClientPacketReceived(NBN_Packet *packet)
{
if (Endpoint_ProcessReceivedPacket(&nbn_game_server.endpoint, packet, packet->sender) < 0)
{
@@ -6229,16 +6362,18 @@ static int PacketSimulator_SendPacket(
return 0;
}
NBN_Driver *driver = receiver->driver;
if (receiver->endpoint->is_server)
{
if (receiver->is_stale)
return 0;
return NBN_Driver_GServ_SendPacketTo(packet, receiver);
return driver->impl.serv_send_packet_to(packet, receiver);
}
else
{
return NBN_Driver_GCli_SendPacket(packet);
return driver->impl.cli_send_packet(packet);
}
}
@@ -6304,7 +6439,7 @@ typedef bitvec_t scalar_t;
#if defined(ECC_CURVE) && (ECC_CURVE != 0)
#if (ECC_CURVE == NIST_K163)
#define coeff_a 1
#define cofactor 2
#define ecdh_cofactor 2
/* NIST K-163 */
const gf2elem_t polynomial = {0x000000c9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008};
const gf2elem_t coeff_b = {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};
@@ -6315,7 +6450,7 @@ const scalar_t base_order = {0x99f8a5ef, 0xa2e0cc0d, 0x00020108, 0x00000000, 0x0
#if (ECC_CURVE == NIST_B163)
#define coeff_a 1
#define cofactor 2
#define ecdh_cofactor 2
/* NIST B-163 */
const gf2elem_t polynomial = {0x000000c9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008};
const gf2elem_t coeff_b = {0x4a3205fd, 0x512f7874, 0x1481eb10, 0xb8c953ca, 0x0a601907, 0x00000002};
@@ -6326,7 +6461,7 @@ const scalar_t base_order = {0xa4234c33, 0x77e70c12, 0x000292fe, 0x00000000, 0x0
#if (ECC_CURVE == NIST_K233)
#define coeff_a 0
#define cofactor 4
#define ecdh_cofactor 4
/* NIST K-233 */
const gf2elem_t polynomial = {0x00000001, 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000200};
const gf2elem_t coeff_b = {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};
@@ -6337,7 +6472,7 @@ const scalar_t base_order = {0xf173abdf, 0x6efb1ad5, 0xb915bcd4, 0x00069d5b, 0x0
#if (ECC_CURVE == NIST_B233)
#define coeff_a 1
#define cofactor 2
#define ecdh_cofactor 2
/* NIST B-233 */
const gf2elem_t polynomial = {0x00000001, 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000200};
const gf2elem_t coeff_b = {0x7d8f90ad, 0x81fe115f, 0x20e9ce42, 0x213b333b, 0x0923bb58, 0x332c7f8c, 0x647ede6c, 0x00000066};
@@ -6348,7 +6483,7 @@ const scalar_t base_order = {0x03cfe0d7, 0x22031d26, 0xe72f8a69, 0x0013e974, 0x0
#if (ECC_CURVE == NIST_K283)
#define coeff_a 0
#define cofactor 4
#define ecdh_cofactor 4
/* NIST K-283 */
const gf2elem_t polynomial = {0x000010a1, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08000000};
const gf2elem_t coeff_b = {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};
@@ -6359,7 +6494,7 @@ const scalar_t base_order = {0x1e163c61, 0x94451e06, 0x265dff7f, 0x2ed07577, 0xf
#if (ECC_CURVE == NIST_B283)
#define coeff_a 1
#define cofactor 2
#define ecdh_cofactor 2
/* NIST B-283 */
const gf2elem_t polynomial = {0x000010a1, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08000000};
const gf2elem_t coeff_b = {0x3b79a2f5, 0xf6263e31, 0xa581485a, 0x45309fa2, 0xca97fd76, 0x19a0303f, 0xa5a4af8a, 0xc8b8596d, 0x027b680a};
@@ -6370,7 +6505,7 @@ const scalar_t base_order = {0xefadb307, 0x5b042a7c, 0x938a9016, 0x399660fc, 0xf
#if (ECC_CURVE == NIST_K409)
#define coeff_a 0
#define cofactor 4
#define ecdh_cofactor 4
/* NIST K-409 */
const gf2elem_t polynomial = {0x00000001, 0x00000000, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02000000};
const gf2elem_t coeff_b = {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};
@@ -6381,7 +6516,7 @@ const scalar_t base_order = {0xe01e5fcf, 0x4b5c83b8, 0xe3e7ca5b, 0x557d5ed3, 0x2
#if (ECC_CURVE == NIST_B409)
#define coeff_a 1
#define cofactor 2
#define ecdh_cofactor 2
/* NIST B-409 */
const gf2elem_t polynomial = {0x00000001, 0x00000000, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02000000};
const gf2elem_t coeff_b = {0x7b13545f, 0x4f50ae31, 0xd57a55aa, 0x72822f6c, 0xa9a197b2, 0xd6ac27c8, 0x4761fa99, 0xf1f3dd67, 0x7fd6422e, 0x3b7b476b, 0x5c4b9a75, 0xc8ee9feb, 0x0021a5c2};
@@ -6392,7 +6527,7 @@ const scalar_t base_order = {0xd9a21173, 0x8164cd37, 0x9e052f83, 0x5fa47c3c, 0xf
#if (ECC_CURVE == NIST_K571)
#define coeff_a 0
#define cofactor 4
#define ecdh_cofactor 4
/* NIST K-571 */
const gf2elem_t polynomial = {0x00000425, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08000000};
const gf2elem_t coeff_b = {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};
@@ -6403,7 +6538,7 @@ const scalar_t base_order = {0x637c1001, 0x5cfe778f, 0x1e91deb4, 0xe5d63938, 0xb
#if (ECC_CURVE == NIST_B571)
#define coeff_a 1
#define cofactor 2
#define ecdh_cofactor 2
/* NIST B-571 */
const gf2elem_t polynomial = {0x00000425, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08000000};
const gf2elem_t coeff_b = {0x2955727a, 0x7ffeff7f, 0x39baca0c, 0x520e4de7, 0x78ff12aa, 0x4afd185a, 0x56a66e29, 0x2be7ad67, 0x8efa5933, 0x84ffabbd, 0x4a9a18ad, 0xcd6ba8ce, 0xcb8ceff1, 0x5c6a97ff, 0xb7f3d62f, 0xde297117, 0x2221f295, 0x02f40e7e};
@@ -6965,9 +7100,9 @@ static int ecdh_shared_secret(const uint8_t *private_key, const uint8_t *others_
/* Multiply outcome by cofactor if using ECC CDH-variant: */
#if defined(ECDH_COFACTOR_VARIANT) && (ECDH_COFACTOR_VARIANT == 1)
#if (cofactor == 2)
#if (ecdh_cofactor == 2)
gf2point_double((uint32_t *)output, (uint32_t *)(output + BITVEC_NBYTES));
#elif (cofactor == 4)
#elif (ecdh_cofactor == 4)
gf2point_double((uint32_t *)output, (uint32_t *)(output + BITVEC_NBYTES));
gf2point_double((uint32_t *)output, (uint32_t *)(output + BITVEC_NBYTES));
#endif
+488
View File
@@ -0,0 +1,488 @@
/*
Copyright (C) 2022 BIAGINI Nathan
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
--- NBNET IPC DRIVER ---
IPC driver for the nbnet library.
IMPORTANT: This driver uses UNXI domain sockets for inter processes communication and therefore is not portable.
How to use:
1. Include this header *once* after the nbnet header in the same file where you defined the NBNET_IMPL macro
2. Call NBN_IPC_Register in both your client and server code before calling NBN_GameClient_Start or NBN_GameServer_Start
*/
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!(defined(__APPLE__) && defined(__MACH__))
#error "The IPC driver can only be used on UNIX systems"
#endif
/**
* Register the driver to nbnet.
*
* @param sock_path Path of the UNIX socket
*/
void NBN_IPC_Register(const char *sock_path);
#ifdef NBNET_IMPL
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/stat.h>
#define NBN_IPC_DRIVER_ID 2
#define NBN_IPC_DRIVER_NAME "IPC"
// IPC messages have a 4 bytes header to store the connection id
#define NBN_IPC_HEADER_SIZE 4
#define NBN_IPC_BUFFER_SIZE NBN_IPC_HEADER_SIZE + NBN_PACKET_MAX_SIZE
#pragma region Hashtable
#define HTABLE_DEFAULT_INITIAL_CAPACITY 32
#define HTABLE_LOAD_FACTOR_THRESHOLD 0.75
typedef struct
{
uint32_t id;
NBN_Connection *conn;
} NBN_IPC_Connection;
typedef struct
{
uint32_t conn_id;
unsigned int slot;
NBN_IPC_Connection *conn;
} NBN_IPC_HTableEntry;
typedef struct
{
NBN_IPC_HTableEntry **internal_array;
unsigned int capacity;
unsigned int count;
float load_factor;
} NBN_IPC_HTable;
static NBN_IPC_HTable *NBN_IPC_HTable_Create(void);
static NBN_IPC_HTable *NBN_IPC_HTable_CreateWithCapacity(unsigned int);
static void NBN_IPC_HTable_Destroy(NBN_IPC_HTable *);
static void NBN_IPC_HTable_Add(NBN_IPC_HTable *, uint32_t, NBN_IPC_Connection *);
static NBN_IPC_Connection *NBN_IPC_HTable_Get(NBN_IPC_HTable *, uint32_t);
static NBN_IPC_Connection *NBN_IPC_HTable_Remove(NBN_IPC_HTable *, uint32_t);
static void NBN_IPC_HTable_InsertEntry(NBN_IPC_HTable *, NBN_IPC_HTableEntry *);
static void NBN_IPC_HTable_RemoveEntry(NBN_IPC_HTable *, NBN_IPC_HTableEntry *);
static unsigned int NBN_IPC_HTable_FindFreeSlot(NBN_IPC_HTable *, NBN_IPC_HTableEntry *, bool *);
static NBN_IPC_HTableEntry *NBN_IPC_HTable_FindEntry(NBN_IPC_HTable *, uint32_t);
static void NBN_IPC_HTable_Grow(NBN_IPC_HTable *);
static NBN_IPC_HTable *NBN_IPC_HTable_Create()
{
return NBN_IPC_HTable_CreateWithCapacity(HTABLE_DEFAULT_INITIAL_CAPACITY);
}
static NBN_IPC_HTable *NBN_IPC_HTable_CreateWithCapacity(unsigned int capacity)
{
NBN_IPC_HTable *htable = NBN_Allocator(sizeof(NBN_IPC_HTable));
htable->internal_array = NBN_Allocator(sizeof(NBN_IPC_HTableEntry *) * capacity);
htable->capacity = capacity;
htable->count = 0;
htable->load_factor = 0;
for (unsigned int i = 0; i < htable->capacity; i++)
htable->internal_array[i] = NULL;
return htable;
}
static void NBN_IPC_HTable_Destroy(NBN_IPC_HTable *htable)
{
for (unsigned int i = 0; i < htable->capacity; i++)
{
NBN_IPC_HTableEntry *entry = htable->internal_array[i];
if (entry)
NBN_Deallocator(entry);
}
NBN_Deallocator(htable->internal_array);
NBN_Deallocator(htable);
}
static void NBN_IPC_HTable_Add(NBN_IPC_HTable *htable, uint32_t conn_id, NBN_IPC_Connection *conn)
{
NBN_IPC_HTableEntry *entry = NBN_Allocator(sizeof(NBN_IPC_HTableEntry));
entry->conn_id = conn_id;
entry->conn = conn;
NBN_IPC_HTable_InsertEntry(htable, entry);
if (htable->load_factor >= HTABLE_LOAD_FACTOR_THRESHOLD)
NBN_IPC_HTable_Grow(htable);
}
static NBN_IPC_Connection *NBN_IPC_HTable_Get(NBN_IPC_HTable *htable, uint32_t conn_id)
{
NBN_IPC_HTableEntry *entry = NBN_IPC_HTable_FindEntry(htable, conn_id);
return entry ? entry->conn : NULL;
}
static NBN_IPC_Connection *NBN_IPC_HTable_Remove(NBN_IPC_HTable *htable, uint32_t conn_id)
{
NBN_IPC_HTableEntry *entry = NBN_IPC_HTable_FindEntry(htable, conn_id);
if (entry)
{
NBN_IPC_HTable_RemoveEntry(htable, entry);
return entry->conn;
}
return NULL;
}
static void NBN_IPC_HTable_InsertEntry(NBN_IPC_HTable *htable, NBN_IPC_HTableEntry *entry)
{
bool use_existing_slot = false;
unsigned int slot = NBN_IPC_HTable_FindFreeSlot(htable, entry, &use_existing_slot);
entry->slot = slot;
htable->internal_array[slot] = entry;
if (!use_existing_slot)
{
htable->count++;
htable->load_factor = (float)htable->count / htable->capacity;
}
}
static void NBN_IPC_HTable_RemoveEntry(NBN_IPC_HTable *htable, NBN_IPC_HTableEntry *entry)
{
htable->internal_array[entry->slot] = NULL;
NBN_Deallocator(entry);
htable->count--;
htable->load_factor = htable->count / htable->capacity;
}
static unsigned int NBN_IPC_HTable_FindFreeSlot(NBN_IPC_HTable *htable, NBN_IPC_HTableEntry *entry, bool *use_existing_slot)
{
unsigned long hash = entry->conn_id;
unsigned int slot;
// quadratic probing
NBN_IPC_HTableEntry *current_entry;
unsigned int i = 0;
do
{
slot = (hash + (int)pow(i, 2)) % htable->capacity;
current_entry = htable->internal_array[slot];
i++;
} while (current_entry != NULL && current_entry->conn_id != entry->conn_id);
if (current_entry != NULL) // it means the current entry as the same key as the inserted entry
{
*use_existing_slot = true;
NBN_Deallocator(current_entry);
}
return slot;
}
static NBN_IPC_HTableEntry *NBN_IPC_HTable_FindEntry(NBN_IPC_HTable *htable, uint32_t conn_id)
{
unsigned long hash = conn_id;
unsigned int slot;
//quadratic probing
NBN_IPC_HTableEntry *current_entry;
unsigned int i = 0;
do
{
slot = (hash + (int)pow(i, 2)) % htable->capacity;
current_entry = htable->internal_array[slot];
if (current_entry != NULL && current_entry->conn_id == conn_id)
{
return current_entry;
}
i++;
} while (i < htable->capacity);
return NULL;
}
static void NBN_IPC_HTable_Grow(NBN_IPC_HTable *htable)
{
unsigned int old_capacity = htable->capacity;
unsigned int new_capacity = old_capacity * 2;
NBN_IPC_HTableEntry** old_internal_array = htable->internal_array;
NBN_IPC_HTableEntry** new_internal_array = NBN_Allocator(sizeof(NBN_IPC_HTableEntry*) * new_capacity);
for (unsigned int i = 0; i < new_capacity; i++)
{
new_internal_array[i] = NULL;
}
htable->internal_array = new_internal_array;
htable->capacity = new_capacity;
htable->count = 0;
htable->load_factor = 0;
// rehash
for (unsigned int i = 0; i < old_capacity; i++)
{
if (old_internal_array[i])
NBN_IPC_HTable_InsertEntry(htable, old_internal_array[i]);
}
NBN_Deallocator(old_internal_array);
}
#pragma endregion // Hashtable
#pragma region Game server
static int unix_sock, unix_sock2;
static struct sockaddr_un unix_sock_addr;
static const char *unix_sock_path;
static NBN_IPC_HTable *nbn_fifo_connections = NULL;
static NBN_Connection *FindOrCreateClientConnectionById(uint32_t id);
static int NBN_IPC_ServStart(uint32_t proto_id, uint16_t port)
{
if ((unix_sock = socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0)
{
NBN_LogError("socket() faied: %s", strerror(errno));
return NBN_ERROR;
}
if ((unix_sock2 = socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0)
{
NBN_LogError("socket() faied: %s", strerror(errno));
return NBN_ERROR;
}
memset(&unix_sock_addr, 0, sizeof(unix_sock_addr));
unix_sock_addr.sun_family = AF_UNIX;
strncpy(unix_sock_addr.sun_path, unix_sock_path, sizeof(unix_sock_addr.sun_path) - 1);
unlink(unix_sock_path);
if (bind(unix_sock, (SOCKADDR *)&unix_sock_addr, sizeof(unix_sock_addr)) < 0)
{
NBN_LogError("bind() failed: %s", strerror(errno));
return NBN_ERROR;
}
if (fcntl(unix_sock, F_SETFL, O_NONBLOCK, 1) < 0)
{
NBN_LogError("fcntl() failed: %s", strerror(errno));
return NBN_ERROR;
}
if (fcntl(unix_sock2, F_SETFL, O_NONBLOCK, 1) < 0)
{
NBN_LogError("fcntl() failed: %s", strerror(errno));
return NBN_ERROR;
}
protocol_id = proto_id;
nbn_fifo_connections = NBN_IPC_HTable_Create();
return 0;
}
static void NBN_IPC_ServStop(void)
{
close(unix_sock);
NBN_IPC_HTable_Destroy(nbn_fifo_connections);
}
static int NBN_IPC_ServRecvPackets(void)
{
uint8_t buffer[NBN_IPC_BUFFER_SIZE] = {0};
while (true)
{
int bytes = recvfrom(unix_sock, (char *)buffer, sizeof(buffer), 0, NULL, NULL);
if (bytes <= 0)
break;
// datagrams should have a valid header followed by the nbnet packet data
if (bytes <= NBN_IPC_HEADER_SIZE)
{
continue;
}
// Start by reading the connection id from the IPC message header
uint32_t conn_id =
((uint32_t)buffer[0] << 24) +
((uint32_t)buffer[1] << 16) +
((uint32_t)buffer[2] << 8) +
(uint32_t)buffer[3];
// Then read and process the actual nbnet packet
uint8_t *packet_buffer = buffer + NBN_IPC_HEADER_SIZE;
unsigned int packet_bytes = bytes - NBN_IPC_HEADER_SIZE;
if (NBN_Packet_ReadProtocolId(packet_buffer, packet_bytes) != protocol_id)
continue; // not matching the protocol of the receiver
NBN_Connection *conn = FindOrCreateClientConnectionById(conn_id);
if (conn == NULL)
continue; // skip the connection
NBN_Packet packet;
if (NBN_Packet_InitRead(&packet, conn, packet_buffer, packet_bytes) < 0)
continue; /* not a valid packet */
if (NBN_Driver_RaiseEvent(NBN_DRIVER_SERV_CLIENT_PACKET_RECEIVED, &packet) < 0)
{
NBN_LogError("Failed to raise game server event");
return NBN_ERROR;
}
}
return 0;
}
static void NBN_IPC_ServRemoveClientConnection(NBN_Connection *connection)
{
assert(connection != NULL);
NBN_IPC_Connection *fifo_conn = NBN_IPC_HTable_Remove(nbn_fifo_connections, ((NBN_IPC_Connection *)connection->driver_data)->id);
if (fifo_conn)
{
NBN_LogDebug("Destroyed IPC connection %d", connection->id);
NBN_Deallocator(fifo_conn);
// TODO: notify removed connection to other service
}
}
static int NBN_IPC_ServSendPacketTo(NBN_Packet *packet, NBN_Connection *connection)
{
NBN_IPC_Connection *fifo_conn = (NBN_IPC_Connection *)connection->driver_data;
uint8_t buffer[NBN_IPC_BUFFER_SIZE];
unsigned int bytes = 0;
memcpy(buffer, &fifo_conn->id, NBN_IPC_HEADER_SIZE);
bytes += NBN_IPC_HEADER_SIZE;
memcpy(buffer + NBN_IPC_HEADER_SIZE, packet->buffer, packet->size);
bytes += packet->size;
NBN_LogDebug("SEND: %s", unix_sock_addr.sun_path);
if (sendto(unix_sock2, (const char *)buffer, bytes, 0, (SOCKADDR *)&unix_sock_addr, sizeof(unix_sock_addr)) == SOCKET_ERROR)
{
NBN_LogError("sendto() failed: %s", strerror(errno));
return NBN_ERROR;
}
return 0;
}
static NBN_Connection *FindOrCreateClientConnectionById(uint32_t id)
{
NBN_IPC_Connection *fifo_conn = NBN_IPC_HTable_Get(nbn_fifo_connections, id);
if (fifo_conn == NULL)
{
/* this is a new connection */
if (GameServer_GetClientCount() >= NBN_MAX_CLIENTS)
return NULL;
fifo_conn = (NBN_IPC_Connection *)NBN_Allocator(sizeof(NBN_IPC_Connection));
fifo_conn->id = id;
fifo_conn->conn = NBN_GameServer_CreateClientConnection(fifo_conn->id, NBN_IPC_DRIVER_ID, fifo_conn);
NBN_IPC_HTable_Add(nbn_fifo_connections, id, fifo_conn);
NBN_LogDebug("New UDP connection (id: %d)", fifo_conn->id);
if (NBN_Driver_RaiseEvent(NBN_DRIVER_SERV_CLIENT_CONNECTED, fifo_conn->conn) < 0)
{
NBN_LogError("Failed to raise game server event");
return NULL;
}
}
return fifo_conn->conn;
}
#pragma endregion /* Game server */
#pragma region Driver registering
void NBN_IPC_Register(const char *sock_path)
{
unix_sock_path = sock_path;
NBN_Driver_Register(
NBN_IPC_DRIVER_ID,
NBN_IPC_DRIVER_NAME,
(NBN_DriverImplementation){
// No client implementation
NULL,
NULL,
NULL,
NULL,
// Server implementation
NBN_IPC_ServStart,
NBN_IPC_ServStop,
NBN_IPC_ServRecvPackets,
NBN_IPC_ServSendPacketTo,
NBN_IPC_ServRemoveClientConnection
}
);
}
#pragma endregion /* Driver registering */
#endif /* NBNET_IMPL */
+3451
View File
File diff suppressed because it is too large. Load diff
+120 -88
View File
@@ -27,15 +27,21 @@ freely, subject to the following restrictions:
How to use:
Include this header *once* after the nbnet header in the same file where you defined the NBNET_IMPL macro.
1. Include this header *once* after the nbnet header in the same file where you defined the NBNET_IMPL macro
2. Call NBN_UDP_Register in both your client and server code before calling NBN_GameClient_Start or NBN_GameServer_Start
*/
void NBN_UDP_Register(void);
#ifdef NBNET_IMPL
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#define NBN_UDP_DRIVER_ID 0
#define NBN_UDP_DRIVER_NAME "UDP"
#pragma region Platform detection
#if defined(_WIN32) || defined(_WIN64)
@@ -87,7 +93,7 @@ typedef struct
uint32_t id;
NBN_IPAddress address;
NBN_Connection *conn; // nbnet connection associated to this UDP connection
} NBN_UDPConnection;
} NBN_UDP_Connection;
static SOCKET udp_sock;
static uint32_t protocol_id;
@@ -102,41 +108,41 @@ static bool CompareIPAddresses(NBN_IPAddress ip_addr1, NBN_IPAddress ip_addr2);
typedef struct
{
NBN_IPAddress ip_addr;
NBN_UDPConnection *conn;
NBN_UDP_Connection *conn;
unsigned int slot;
} HTableEntry;
} NBN_UDP_HTableEntry;
typedef struct
{
HTableEntry **internal_array;
NBN_UDP_HTableEntry **internal_array;
unsigned int capacity;
unsigned int count;
float load_factor;
} HTable;
} NBN_UDP_HTable;
static HTable *HTable_Create();
static HTable *HTable_CreateWithCapacity(unsigned int);
static void HTable_Destroy(HTable *);
static void HTable_Add(HTable *, NBN_IPAddress, NBN_UDPConnection *);
static NBN_UDPConnection *HTable_Get(HTable *, NBN_IPAddress);
static NBN_UDPConnection *HTable_Remove(HTable *, NBN_IPAddress);
static void HTable_InsertEntry(HTable *, HTableEntry *);
static void HTable_RemoveEntry(HTable *, HTableEntry *);
static unsigned int HTable_FindFreeSlot(HTable *, HTableEntry *, bool *);
static HTableEntry *HTable_FindEntry(HTable *, NBN_IPAddress);
static void HTable_Grow(HTable *);
static unsigned long HTable_HashSDBM(NBN_IPAddress);
static NBN_UDP_HTable *NBN_UDP_HTable_Create(void);
static NBN_UDP_HTable *NBN_UDP_HTable_CreateWithCapacity(unsigned int);
static void NBN_UDP_HTable_Destroy(NBN_UDP_HTable *);
static void NBN_UDP_HTable_Add(NBN_UDP_HTable *, NBN_IPAddress, NBN_UDP_Connection *);
static NBN_UDP_Connection *NBN_UDP_HTable_Get(NBN_UDP_HTable *, NBN_IPAddress);
static NBN_UDP_Connection *NBN_UDP_HTable_Remove(NBN_UDP_HTable *, NBN_IPAddress);
static void NBN_UDP_HTable_InsertEntry(NBN_UDP_HTable *, NBN_UDP_HTableEntry *);
static void NBN_UDP_HTable_RemoveEntry(NBN_UDP_HTable *, NBN_UDP_HTableEntry *);
static unsigned int NBN_UDP_HTable_FindFreeSlot(NBN_UDP_HTable *, NBN_UDP_HTableEntry *, bool *);
static NBN_UDP_HTableEntry *NBN_UDP_HTable_FindEntry(NBN_UDP_HTable *, NBN_IPAddress);
static void NBN_UDP_HTable_Grow(NBN_UDP_HTable *);
static unsigned long NBN_UDP_HTable_HashSDBM(NBN_IPAddress);
HTable *HTable_Create()
static NBN_UDP_HTable *NBN_UDP_HTable_Create(void)
{
return HTable_CreateWithCapacity(HTABLE_DEFAULT_INITIAL_CAPACITY);
return NBN_UDP_HTable_CreateWithCapacity(HTABLE_DEFAULT_INITIAL_CAPACITY);
}
HTable *HTable_CreateWithCapacity(unsigned int capacity)
static NBN_UDP_HTable *NBN_UDP_HTable_CreateWithCapacity(unsigned int capacity)
{
HTable *htable = NBN_Allocator(sizeof(HTable));
NBN_UDP_HTable *htable = NBN_Allocator(sizeof(NBN_UDP_HTable));
htable->internal_array = NBN_Allocator(sizeof(HTableEntry *) * capacity);
htable->internal_array = NBN_Allocator(sizeof(NBN_UDP_HTableEntry *) * capacity);
htable->capacity = capacity;
htable->count = 0;
htable->load_factor = 0;
@@ -147,11 +153,11 @@ HTable *HTable_CreateWithCapacity(unsigned int capacity)
return htable;
}
void HTable_Destroy(HTable *htable)
static void NBN_UDP_HTable_Destroy(NBN_UDP_HTable *htable)
{
for (unsigned int i = 0; i < htable->capacity; i++)
{
HTableEntry *entry = htable->internal_array[i];
NBN_UDP_HTableEntry *entry = htable->internal_array[i];
if (entry)
NBN_Deallocator(entry);
@@ -161,33 +167,33 @@ void HTable_Destroy(HTable *htable)
NBN_Deallocator(htable);
}
static void HTable_Add(HTable *htable, NBN_IPAddress ip_addr, NBN_UDPConnection *conn)
static void NBN_UDP_HTable_Add(NBN_UDP_HTable *htable, NBN_IPAddress ip_addr, NBN_UDP_Connection *conn)
{
HTableEntry *entry = NBN_Allocator(sizeof(HTableEntry));
NBN_UDP_HTableEntry *entry = NBN_Allocator(sizeof(NBN_UDP_HTableEntry));
entry->ip_addr = ip_addr;
entry->conn = conn;
HTable_InsertEntry(htable, entry);
NBN_UDP_HTable_InsertEntry(htable, entry);
if (htable->load_factor >= HTABLE_LOAD_FACTOR_THRESHOLD)
HTable_Grow(htable);
NBN_UDP_HTable_Grow(htable);
}
NBN_UDPConnection *HTable_Get(HTable *htable, NBN_IPAddress ip_addr)
static NBN_UDP_Connection *NBN_UDP_HTable_Get(NBN_UDP_HTable *htable, NBN_IPAddress ip_addr)
{
HTableEntry *entry = HTable_FindEntry(htable, ip_addr);
NBN_UDP_HTableEntry *entry = NBN_UDP_HTable_FindEntry(htable, ip_addr);
return entry ? entry->conn : NULL;
}
static NBN_UDPConnection *HTable_Remove(HTable *htable, NBN_IPAddress ip_addr)
static NBN_UDP_Connection *NBN_UDP_HTable_Remove(NBN_UDP_HTable *htable, NBN_IPAddress ip_addr)
{
HTableEntry *entry = HTable_FindEntry(htable, ip_addr);
NBN_UDP_HTableEntry *entry = NBN_UDP_HTable_FindEntry(htable, ip_addr);
if (entry)
{
HTable_RemoveEntry(htable, entry);
NBN_UDP_HTable_RemoveEntry(htable, entry);
return entry->conn;
}
@@ -195,10 +201,10 @@ static NBN_UDPConnection *HTable_Remove(HTable *htable, NBN_IPAddress ip_addr)
return NULL;
}
static void HTable_InsertEntry(HTable *htable, HTableEntry *entry)
static void NBN_UDP_HTable_InsertEntry(NBN_UDP_HTable *htable, NBN_UDP_HTableEntry *entry)
{
bool use_existing_slot = false;
unsigned int slot = HTable_FindFreeSlot(htable, entry, &use_existing_slot);
unsigned int slot = NBN_UDP_HTable_FindFreeSlot(htable, entry, &use_existing_slot);
entry->slot = slot;
htable->internal_array[slot] = entry;
@@ -210,7 +216,7 @@ static void HTable_InsertEntry(HTable *htable, HTableEntry *entry)
}
}
static void HTable_RemoveEntry(HTable *htable, HTableEntry *entry)
static void NBN_UDP_HTable_RemoveEntry(NBN_UDP_HTable *htable, NBN_UDP_HTableEntry *entry)
{
htable->internal_array[entry->slot] = NULL;
@@ -220,14 +226,14 @@ static void HTable_RemoveEntry(HTable *htable, HTableEntry *entry)
htable->load_factor = htable->count / htable->capacity;
}
static unsigned int HTable_FindFreeSlot(HTable *htable, HTableEntry *entry, bool *use_existing_slot)
static unsigned int NBN_UDP_HTable_FindFreeSlot(NBN_UDP_HTable *htable, NBN_UDP_HTableEntry *entry, bool *use_existing_slot)
{
unsigned long hash = HTable_HashSDBM(entry->ip_addr);
unsigned long hash = NBN_UDP_HTable_HashSDBM(entry->ip_addr);
unsigned int slot;
// quadratic probing
HTableEntry *current_entry;
NBN_UDP_HTableEntry *current_entry;
unsigned int i = 0;
do
@@ -248,14 +254,14 @@ static unsigned int HTable_FindFreeSlot(HTable *htable, HTableEntry *entry, bool
return slot;
}
static HTableEntry *HTable_FindEntry(HTable *htable, NBN_IPAddress ip_addr)
static NBN_UDP_HTableEntry *NBN_UDP_HTable_FindEntry(NBN_UDP_HTable *htable, NBN_IPAddress ip_addr)
{
unsigned long hash = HTable_HashSDBM(ip_addr);
unsigned long hash = NBN_UDP_HTable_HashSDBM(ip_addr);
unsigned int slot;
//quadratic probing
HTableEntry *current_entry;
NBN_UDP_HTableEntry *current_entry;
unsigned int i = 0;
do
@@ -274,12 +280,12 @@ static HTableEntry *HTable_FindEntry(HTable *htable, NBN_IPAddress ip_addr)
return NULL;
}
static void HTable_Grow(HTable *htable)
static void NBN_UDP_HTable_Grow(NBN_UDP_HTable *htable)
{
unsigned int old_capacity = htable->capacity;
unsigned int new_capacity = old_capacity * 2;
HTableEntry** old_internal_array = htable->internal_array;
HTableEntry** new_internal_array = NBN_Allocator(sizeof(HTableEntry*) * new_capacity);
NBN_UDP_HTableEntry** old_internal_array = htable->internal_array;
NBN_UDP_HTableEntry** new_internal_array = NBN_Allocator(sizeof(NBN_UDP_HTableEntry*) * new_capacity);
for (unsigned int i = 0; i < new_capacity; i++)
{
@@ -296,13 +302,13 @@ static void HTable_Grow(HTable *htable)
for (unsigned int i = 0; i < old_capacity; i++)
{
if (old_internal_array[i])
HTable_InsertEntry(htable, old_internal_array[i]);
NBN_UDP_HTable_InsertEntry(htable, old_internal_array[i]);
}
NBN_Deallocator(old_internal_array);
}
static unsigned long HTable_HashSDBM(NBN_IPAddress ip_addr)
static unsigned long NBN_UDP_HTable_HashSDBM(NBN_IPAddress ip_addr)
{
return ip_addr.host ^ ip_addr.port;
}
@@ -331,12 +337,12 @@ static int InitSocket(void)
{
NBN_LogError("WSAStartup() failed");
return -1;
return NBN_ERROR;
}
#endif
if ((udp_sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
return -1;
return NBN_ERROR;
#if defined(PLATFORM_WINDOWS)
DWORD non_blocking = 1;
@@ -345,7 +351,7 @@ static int InitSocket(void)
{
NBN_LogError("ioctlsocket() failed: %s", GetLastErrorMessage());
return -1;
return NBN_ERROR;
}
#elif defined(PLATFORM_MAC) || defined(PLATFORM_UNIX)
int non_blocking = 1;
@@ -354,7 +360,7 @@ static int InitSocket(void)
{
NBN_LogError("fcntl() failed: %s", GetLastErrorMessage());
return -1;
return NBN_ERROR;
}
#endif
@@ -382,7 +388,7 @@ static int BindSocket(uint16_t port)
{
NBN_LogError("bind() failed: %s", GetLastErrorMessage());
return -1;
return NBN_ERROR;
}
return 0;
@@ -398,13 +404,13 @@ static int ResolveIpAddress(const char *host, uint16_t port, NBN_IPAddress *addr
char *s;
if ((s = strtok(i == 0 ? dup_host : NULL, ".")) == NULL)
return -1;
return NBN_ERROR;
char *end = NULL;
int v = strtol(s, &end, 10);
if (end == s || v < 0 || v > 255)
return -1;
return NBN_ERROR;
arr[i] = (uint8_t)v;
}
@@ -432,32 +438,32 @@ static char *GetLastErrorMessage(void)
#pragma region Game server
static HTable *__clients = NULL;
static NBN_UDP_HTable *nbn_udp_connections = NULL;
static uint32_t next_conn_id = 0;
static NBN_Connection *FindOrCreateClientConnectionByAddress(NBN_IPAddress);
int NBN_Driver_GServ_Start(uint32_t proto_id, uint16_t port)
static int NBN_UDP_ServStart(uint32_t proto_id, uint16_t port)
{
protocol_id = proto_id;
__clients = HTable_Create();
nbn_udp_connections = NBN_UDP_HTable_Create();
if (InitSocket() < 0)
return -1;
return NBN_ERROR;
if (BindSocket(port) < 0)
return -1;
return NBN_ERROR;
return 0;
}
void NBN_Driver_GServ_Stop(void)
static void NBN_UDP_ServStop(void)
{
HTable_Destroy(__clients);
NBN_UDP_HTable_Destroy(nbn_udp_connections);
DeinitSocket();
}
int NBN_Driver_GServ_RecvPackets(void)
static int NBN_UDP_ServRecvPackets(void)
{
uint8_t buffer[NBN_PACKET_MAX_SIZE] = {0};
SOCKADDR_IN src_addr;
@@ -487,7 +493,7 @@ int NBN_Driver_GServ_RecvPackets(void)
if (NBN_Packet_InitRead(&packet, conn, buffer, bytes) < 0)
continue; /* not a valid packet */
if (NBN_Driver_GServ_RaiseEvent(NBN_DRIVER_GSERV_CLIENT_PACKET_RECEIVED, &packet) < 0)
if (NBN_Driver_RaiseEvent(NBN_DRIVER_SERV_CLIENT_PACKET_RECEIVED, &packet) < 0)
{
NBN_LogError("Failed to raise game server event");
@@ -498,11 +504,11 @@ int NBN_Driver_GServ_RecvPackets(void)
return 0;
}
void NBN_Driver_GServ_RemoveClientConnection(NBN_Connection *connection)
static void NBN_UDP_ServRemoveClientConnection(NBN_Connection *connection)
{
assert(connection != NULL);
NBN_UDPConnection *udp_conn = HTable_Remove(__clients, ((NBN_UDPConnection *)connection->driver_data)->address);
NBN_UDP_Connection *udp_conn = NBN_UDP_HTable_Remove(nbn_udp_connections, ((NBN_UDP_Connection *)connection->driver_data)->address);
if (udp_conn)
{
@@ -512,9 +518,9 @@ void NBN_Driver_GServ_RemoveClientConnection(NBN_Connection *connection)
}
}
int NBN_Driver_GServ_SendPacketTo(NBN_Packet *packet, NBN_Connection *connection)
static int NBN_UDP_ServSendPacketTo(NBN_Packet *packet, NBN_Connection *connection)
{
NBN_UDPConnection *udp_conn = (NBN_UDPConnection*)connection->driver_data;
NBN_UDP_Connection *udp_conn = (NBN_UDP_Connection *)connection->driver_data;
SOCKADDR_IN dest_addr;
@@ -526,7 +532,7 @@ int NBN_Driver_GServ_SendPacketTo(NBN_Packet *packet, NBN_Connection *connection
{
NBN_LogError("sendto() failed: %s", GetLastErrorMessage());
return -1;
return NBN_ERROR;
}
return 0;
@@ -534,7 +540,7 @@ int NBN_Driver_GServ_SendPacketTo(NBN_Packet *packet, NBN_Connection *connection
static NBN_Connection *FindOrCreateClientConnectionByAddress(NBN_IPAddress address)
{
NBN_UDPConnection *udp_conn = HTable_Get(__clients, address);
NBN_UDP_Connection *udp_conn = NBN_UDP_HTable_Get(nbn_udp_connections, address);
if (udp_conn == NULL)
{
@@ -543,17 +549,17 @@ static NBN_Connection *FindOrCreateClientConnectionByAddress(NBN_IPAddress addre
if (GameServer_GetClientCount() >= NBN_MAX_CLIENTS)
return NULL;
udp_conn = (NBN_UDPConnection *)NBN_Allocator(sizeof(NBN_UDPConnection));
udp_conn = (NBN_UDP_Connection *)NBN_Allocator(sizeof(NBN_UDP_Connection));
udp_conn->id = next_conn_id++;
udp_conn->address = address;
udp_conn->conn = NBN_GameServer_CreateClientConnection(udp_conn->id, udp_conn);
udp_conn->conn = NBN_GameServer_CreateClientConnection(udp_conn->id, NBN_UDP_DRIVER_ID, udp_conn);
HTable_Add(__clients, address, udp_conn);
NBN_UDP_HTable_Add(nbn_udp_connections, address, udp_conn);
NBN_LogDebug("New UDP connection (id: %d)", udp_conn->id);
if (NBN_Driver_GServ_RaiseEvent(NBN_DRIVER_GSERV_CLIENT_CONNECTED, udp_conn->conn) < 0)
if (NBN_Driver_RaiseEvent(NBN_DRIVER_SERV_CLIENT_CONNECTED, udp_conn->conn) < 0)
{
NBN_LogError("Failed to raise game server event");
@@ -578,9 +584,9 @@ static bool is_connected_to_server = false;
static int ResolveIpAddress(const char *, uint16_t, NBN_IPAddress *);
int NBN_Driver_GCli_Start(uint32_t proto_id, const char *host, uint16_t port)
static int NBN_UDP_CliStart(uint32_t proto_id, const char *host, uint16_t port)
{
NBN_UDPConnection *udp_conn = (NBN_UDPConnection*)NBN_Allocator(sizeof(NBN_Connection));
NBN_UDP_Connection *udp_conn = (NBN_UDP_Connection*)NBN_Allocator(sizeof(NBN_Connection));
protocol_id = proto_id;
@@ -588,28 +594,28 @@ int NBN_Driver_GCli_Start(uint32_t proto_id, const char *host, uint16_t port)
{
NBN_LogError("Failed to resolve IP address from %s", host);
return -1;
return NBN_ERROR;
}
if (InitSocket() < 0)
return -1;
return NBN_ERROR;
if (BindSocket(0) < 0)
return -1;
return NBN_ERROR;
server_connection = NBN_GameClient_CreateServerConnection(udp_conn);
server_connection = NBN_GameClient_CreateServerConnection(NBN_UDP_DRIVER_ID, udp_conn);
return 0;
}
void NBN_Driver_GCli_Stop(void)
static void NBN_UDP_CliStop(void)
{
DeinitSocket();
}
int NBN_Driver_GCli_RecvPackets(void)
static int NBN_UDP_CliRecvPackets(void)
{
NBN_UDPConnection *udp_conn = (NBN_UDPConnection*)server_connection->driver_data;
NBN_UDP_Connection *udp_conn = (NBN_UDP_Connection*)server_connection->driver_data;
uint8_t buffer[NBN_PACKET_MAX_SIZE] = {0};
SOCKADDR_IN src_addr;
socklen_t src_addr_len = sizeof(src_addr);
@@ -641,20 +647,20 @@ int NBN_Driver_GCli_RecvPackets(void)
/* First received packet from server triggers the client connected event */
if (!is_connected_to_server)
{
NBN_Driver_GCli_RaiseEvent(NBN_DRIVER_GCLI_CONNECTED, NULL);
NBN_Driver_RaiseEvent(NBN_DRIVER_CLI_CONNECTED, NULL);
is_connected_to_server = true;
}
NBN_Driver_GCli_RaiseEvent(NBN_DRIVER_GCLI_SERVER_PACKET_RECEIVED, &packet);
NBN_Driver_RaiseEvent(NBN_DRIVER_CLI_PACKET_RECEIVED, &packet);
}
return 0;
}
int NBN_Driver_GCli_SendPacket(NBN_Packet *packet)
static int NBN_UDP_CliSendPacket(NBN_Packet *packet)
{
NBN_UDPConnection *udp_conn = (NBN_UDPConnection *)server_connection->driver_data;
NBN_UDP_Connection *udp_conn = (NBN_UDP_Connection *)server_connection->driver_data;
SOCKADDR_IN dest_addr;
dest_addr.sin_addr.s_addr = htonl(udp_conn->address.host);
@@ -665,7 +671,7 @@ int NBN_Driver_GCli_SendPacket(NBN_Packet *packet)
{
NBN_LogError("sendto() failed: %s", GetLastErrorMessage());
return -1;
return NBN_ERROR;
}
return 0;
@@ -673,4 +679,30 @@ int NBN_Driver_GCli_SendPacket(NBN_Packet *packet)
#pragma endregion /* Game client */
#pragma region Driver registering
void NBN_UDP_Register(void)
{
NBN_Driver_Register(
NBN_UDP_DRIVER_ID,
NBN_UDP_DRIVER_NAME,
(NBN_DriverImplementation){
// Client implementation
NBN_UDP_CliStart,
NBN_UDP_CliStop,
NBN_UDP_CliRecvPackets,
NBN_UDP_CliSendPacket,
// Server implementation
NBN_UDP_ServStart,
NBN_UDP_ServStop,
NBN_UDP_ServRecvPackets,
NBN_UDP_ServSendPacketTo,
NBN_UDP_ServRemoveClientConnection
}
);
}
#pragma endregion /* Driver registering */
#endif /* NBNET_IMPL */
+101 -69
View File
@@ -27,9 +27,12 @@ freely, subject to the following restrictions:
How to use:
Include this header *once* after the nbnet header in the same file where you defined the NBNET_IMPL macro.
1. Include this header *once* after the nbnet header in the same file where you defined the NBNET_IMPL macro
2. Call NBN_WebRTC_Register in both your client and server code before calling NBN_GameClient_Start or NBN_GameServer_Start
*/
void NBN_WebRTC_Register(void);
#ifdef NBNET_IMPL
#if !defined(EXTERN_C)
@@ -42,11 +45,14 @@ freely, subject to the following restrictions:
#include <emscripten/emscripten.h>
#define NBN_WEBRTC_DRIVER_ID 1
#define NBN_WEBRTC_DRIVER_NAME "WebRTC"
typedef struct
{
uint32_t id;
NBN_Connection *conn;
} NBN_Peer;
} NBN_WebRTC_Peer;
#pragma region Hashtable
@@ -56,40 +62,40 @@ typedef struct
typedef struct
{
uint32_t peer_id;
NBN_Peer *peer;
NBN_WebRTC_Peer *peer;
unsigned int slot;
} HTableEntry;
} NBN_WebRTC_HTableEntry;
typedef struct
{
HTableEntry **internal_array;
NBN_WebRTC_HTableEntry **internal_array;
unsigned int capacity;
unsigned int count;
float load_factor;
} HTable;
} NBN_WebRTC_HTable;
static HTable *HTable_Create();
static HTable *HTable_CreateWithCapacity(unsigned int);
static void HTable_Destroy(HTable *);
static void HTable_Add(HTable *, uint32_t, NBN_Peer *);
static NBN_Peer *HTable_Get(HTable *, uint32_t);
static NBN_Peer *HTable_Remove(HTable *, uint32_t);
static void HTable_InsertEntry(HTable *, HTableEntry *);
static void HTable_RemoveEntry(HTable *, HTableEntry *);
static unsigned int HTable_FindFreeSlot(HTable *, HTableEntry *, bool *);
static HTableEntry *HTable_FindEntry(HTable *, uint32_t);
static void HTable_Grow(HTable *);
static NBN_WebRTC_HTable *NBN_WebRTC_HTable_Create(void);
static NBN_WebRTC_HTable *NBN_WebRTC_HTable_CreateWithCapacity(unsigned int);
static void NBN_WebRTC_HTable_Destroy(NBN_WebRTC_HTable *);
static void NBN_WebRTC_HTable_Add(NBN_WebRTC_HTable *, uint32_t, NBN_WebRTC_Peer *);
static NBN_WebRTC_Peer *NBN_WebRTC_HTable_Get(NBN_WebRTC_HTable *, uint32_t);
static NBN_WebRTC_Peer *NBN_WebRTC_HTable_Remove(NBN_WebRTC_HTable *, uint32_t);
static void NBN_WebRTC_HTable_InsertEntry(NBN_WebRTC_HTable *, NBN_WebRTC_HTableEntry *);
static void NBN_WebRTC_HTable_RemoveEntry(NBN_WebRTC_HTable *, NBN_WebRTC_HTableEntry *);
static unsigned int NBN_WebRTC_HTable_FindFreeSlot(NBN_WebRTC_HTable *, NBN_WebRTC_HTableEntry *, bool *);
static NBN_WebRTC_HTableEntry *NBN_WebRTC_HTable_FindEntry(NBN_WebRTC_HTable *, uint32_t);
static void NBN_WebRTC_HTable_Grow(NBN_WebRTC_HTable *);
HTable *HTable_Create()
static NBN_WebRTC_HTable *NBN_WebRTC_HTable_Create(void)
{
return HTable_CreateWithCapacity(HTABLE_DEFAULT_INITIAL_CAPACITY);
return NBN_WebRTC_HTable_CreateWithCapacity(HTABLE_DEFAULT_INITIAL_CAPACITY);
}
HTable *HTable_CreateWithCapacity(unsigned int capacity)
static NBN_WebRTC_HTable *NBN_WebRTC_HTable_CreateWithCapacity(unsigned int capacity)
{
HTable *htable = NBN_Allocator(sizeof(HTable));
NBN_WebRTC_HTable *htable = NBN_Allocator(sizeof(NBN_WebRTC_HTable));
htable->internal_array = NBN_Allocator(sizeof(HTableEntry *) * capacity);
htable->internal_array = NBN_Allocator(sizeof(NBN_WebRTC_HTableEntry *) * capacity);
htable->capacity = capacity;
htable->count = 0;
htable->load_factor = 0;
@@ -100,11 +106,11 @@ HTable *HTable_CreateWithCapacity(unsigned int capacity)
return htable;
}
void HTable_Destroy(HTable *htable)
static void NBN_WebRTC_HTable_Destroy(NBN_WebRTC_HTable *htable)
{
for (unsigned int i = 0; i < htable->capacity; i++)
{
HTableEntry *entry = htable->internal_array[i];
NBN_WebRTC_HTableEntry *entry = htable->internal_array[i];
if (entry)
NBN_Deallocator(entry);
@@ -114,35 +120,35 @@ void HTable_Destroy(HTable *htable)
NBN_Deallocator(htable);
}
static void HTable_Add(HTable *htable, uint32_t peer_id, NBN_Peer *peer)
static void NBN_WebRTC_HTable_Add(NBN_WebRTC_HTable *htable, uint32_t peer_id, NBN_WebRTC_Peer *peer)
{
HTableEntry *entry = NBN_Allocator(sizeof(HTableEntry));
NBN_WebRTC_HTableEntry *entry = NBN_Allocator(sizeof(NBN_WebRTC_HTableEntry));
entry->peer_id = peer_id;
entry->peer = peer;
HTable_InsertEntry(htable, entry);
NBN_WebRTC_HTable_InsertEntry(htable, entry);
if (htable->load_factor >= HTABLE_LOAD_FACTOR_THRESHOLD)
HTable_Grow(htable);
NBN_WebRTC_HTable_Grow(htable);
}
NBN_Peer *HTable_Get(HTable *htable, uint32_t peer_id)
static NBN_WebRTC_Peer *NBN_WebRTC_HTable_Get(NBN_WebRTC_HTable *htable, uint32_t peer_id)
{
HTableEntry *entry = HTable_FindEntry(htable, peer_id);
NBN_WebRTC_HTableEntry *entry = NBN_WebRTC_HTable_FindEntry(htable, peer_id);
return entry ? entry->peer : NULL;
}
static NBN_Peer *HTable_Remove(HTable *htable, uint32_t peer_id)
static NBN_WebRTC_Peer *NBN_WebRTC_HTable_Remove(NBN_WebRTC_HTable *htable, uint32_t peer_id)
{
HTableEntry *entry = HTable_FindEntry(htable, peer_id);
NBN_WebRTC_HTableEntry *entry = NBN_WebRTC_HTable_FindEntry(htable, peer_id);
if (entry)
{
NBN_Peer *peer = entry->peer;
NBN_WebRTC_Peer *peer = entry->peer;
HTable_RemoveEntry(htable, entry);
NBN_WebRTC_HTable_RemoveEntry(htable, entry);
return peer;
}
@@ -150,10 +156,10 @@ static NBN_Peer *HTable_Remove(HTable *htable, uint32_t peer_id)
return NULL;
}
static void HTable_InsertEntry(HTable *htable, HTableEntry *entry)
static void NBN_WebRTC_HTable_InsertEntry(NBN_WebRTC_HTable *htable, NBN_WebRTC_HTableEntry *entry)
{
bool use_existing_slot = false;
unsigned int slot = HTable_FindFreeSlot(htable, entry, &use_existing_slot);
unsigned int slot = NBN_WebRTC_HTable_FindFreeSlot(htable, entry, &use_existing_slot);
entry->slot = slot;
htable->internal_array[slot] = entry;
@@ -165,7 +171,7 @@ static void HTable_InsertEntry(HTable *htable, HTableEntry *entry)
}
}
static void HTable_RemoveEntry(HTable *htable, HTableEntry *entry)
static void NBN_WebRTC_HTable_RemoveEntry(NBN_WebRTC_HTable *htable, NBN_WebRTC_HTableEntry *entry)
{
htable->internal_array[entry->slot] = NULL;
@@ -175,14 +181,14 @@ static void HTable_RemoveEntry(HTable *htable, HTableEntry *entry)
htable->load_factor = htable->count / htable->capacity;
}
static unsigned int HTable_FindFreeSlot(HTable *htable, HTableEntry *entry, bool *use_existing_slot)
static unsigned int NBN_WebRTC_HTable_FindFreeSlot(NBN_WebRTC_HTable *htable, NBN_WebRTC_HTableEntry *entry, bool *use_existing_slot)
{
unsigned long hash = entry->peer_id;
unsigned int slot;
// quadratic probing
HTableEntry *current_entry;
NBN_WebRTC_HTableEntry *current_entry;
unsigned int i = 0;
do
@@ -203,14 +209,14 @@ static unsigned int HTable_FindFreeSlot(HTable *htable, HTableEntry *entry, bool
return slot;
}
static HTableEntry *HTable_FindEntry(HTable *htable, uint32_t peer_id)
static NBN_WebRTC_HTableEntry *NBN_WebRTC_HTable_FindEntry(NBN_WebRTC_HTable *htable, uint32_t peer_id)
{
unsigned long hash = peer_id;
unsigned int slot;
//quadratic probing
HTableEntry *current_entry;
NBN_WebRTC_HTableEntry *current_entry;
unsigned int i = 0;
do
@@ -229,12 +235,12 @@ static HTableEntry *HTable_FindEntry(HTable *htable, uint32_t peer_id)
return NULL;
}
static void HTable_Grow(HTable *htable)
static void NBN_WebRTC_HTable_Grow(NBN_WebRTC_HTable *htable)
{
unsigned int old_capacity = htable->capacity;
unsigned int new_capacity = old_capacity * 2;
HTableEntry** old_internal_array = htable->internal_array;
HTableEntry** new_internal_array = NBN_Allocator(sizeof(HTableEntry*) * new_capacity);
NBN_WebRTC_HTableEntry** old_internal_array = htable->internal_array;
NBN_WebRTC_HTableEntry** new_internal_array = NBN_Allocator(sizeof(NBN_WebRTC_HTableEntry*) * new_capacity);
for (unsigned int i = 0; i < new_capacity; i++)
{
@@ -251,7 +257,7 @@ static void HTable_Grow(HTable *htable)
for (unsigned int i = 0; i < old_capacity; i++)
{
if (old_internal_array[i])
HTable_InsertEntry(htable, old_internal_array[i]);
NBN_WebRTC_HTable_InsertEntry(htable, old_internal_array[i]);
}
NBN_Deallocator(old_internal_array);
@@ -272,9 +278,9 @@ NBN_EXTERN void __js_game_server_stop(void);
/* --- Driver implementation --- */
static HTable *__peers = NULL;
static NBN_WebRTC_HTable *nbn_wrtc_peers = NULL;
int NBN_Driver_GServ_Start(uint32_t protocol_id, uint16_t port)
static int NBN_WebRTC_ServStart(uint32_t protocol_id, uint16_t port)
{
#ifdef NBN_USE_HTTPS
@@ -293,18 +299,18 @@ int NBN_Driver_GServ_Start(uint32_t protocol_id, uint16_t port)
if (__js_game_server_start(port) < 0)
return -1;
__peers = HTable_Create();
nbn_wrtc_peers = NBN_WebRTC_HTable_Create();
return 0;
}
void NBN_Driver_GServ_Stop(void)
static void NBN_WebRTC_ServStop(void)
{
__js_game_server_stop();
HTable_Destroy(__peers);
NBN_WebRTC_HTable_Destroy(nbn_wrtc_peers);
}
int NBN_Driver_GServ_RecvPackets(void)
static int NBN_WebRTC_ServRecvPackets(void)
{
uint8_t *data;
uint32_t peer_id;
@@ -314,7 +320,7 @@ int NBN_Driver_GServ_RecvPackets(void)
{
NBN_Packet packet;
NBN_Peer *peer = HTable_Get(__peers, peer_id);
NBN_WebRTC_Peer *peer = NBN_WebRTC_HTable_Get(nbn_wrtc_peers, peer_id);
if (peer == NULL)
{
@@ -323,14 +329,14 @@ int NBN_Driver_GServ_RecvPackets(void)
NBN_LogTrace("Peer %d has connected", peer_id);
peer = (NBN_Peer *)NBN_Allocator(sizeof(NBN_Peer));
peer = (NBN_WebRTC_Peer *)NBN_Allocator(sizeof(NBN_WebRTC_Peer));
peer->id = peer_id;
peer->conn = NBN_GameServer_CreateClientConnection(peer_id, peer);
peer->conn = NBN_GameServer_CreateClientConnection(peer_id, NBN_WEBRTC_DRIVER_ID, peer);
HTable_Add(__peers, peer_id, peer);
NBN_WebRTC_HTable_Add(nbn_wrtc_peers, peer_id, peer);
NBN_Driver_GServ_RaiseEvent(NBN_DRIVER_GSERV_CLIENT_CONNECTED, peer->conn);
NBN_Driver_RaiseEvent(NBN_DRIVER_SERV_CLIENT_CONNECTED, peer->conn);
}
if (NBN_Packet_InitRead(&packet, peer->conn, data, len) < 0)
@@ -338,19 +344,19 @@ int NBN_Driver_GServ_RecvPackets(void)
packet.sender = peer->conn;
NBN_Driver_GServ_RaiseEvent(NBN_DRIVER_GSERV_CLIENT_PACKET_RECEIVED, &packet);
NBN_Driver_RaiseEvent(NBN_DRIVER_SERV_CLIENT_PACKET_RECEIVED, &packet);
}
return 0;
}
void NBN_Driver_GServ_RemoveClientConnection(NBN_Connection *conn)
static void NBN_WebRTC_ServRemoveClientConnection(NBN_Connection *conn)
{
assert(conn != NULL);
__js_game_server_close_client_peer(conn->id);
NBN_Peer *peer = HTable_Remove(__peers, ((NBN_Peer *)conn->driver_data)->id);
NBN_WebRTC_Peer *peer = NBN_WebRTC_HTable_Remove(nbn_wrtc_peers, ((NBN_WebRTC_Peer *)conn->driver_data)->id);
if (peer)
{
@@ -360,7 +366,7 @@ void NBN_Driver_GServ_RemoveClientConnection(NBN_Connection *conn)
}
}
int NBN_Driver_GServ_SendPacketTo(NBN_Packet *packet, NBN_Connection *conn)
static int NBN_WebRTC_ServSendPacketTo(NBN_Packet *packet, NBN_Connection *conn)
{
return __js_game_server_send_packet_to(packet->buffer, packet->size, conn->id);
}
@@ -379,10 +385,10 @@ NBN_EXTERN void __js_game_client_close(void);
/* --- Driver implementation --- */
static NBN_Connection *server = NULL;
static NBN_Connection *nbn_wrtc_server = NULL;
static bool is_connected_to_server = false;
int NBN_Driver_GCli_Start(uint32_t protocol_id, const char *host, uint16_t port)
static int NBN_WebRTC_CliStart(uint32_t protocol_id, const char *host, uint16_t port)
{
#ifdef NBN_USE_HTTPS
__js_game_client_init(protocol_id, true);
@@ -390,7 +396,7 @@ int NBN_Driver_GCli_Start(uint32_t protocol_id, const char *host, uint16_t port)
__js_game_client_init(protocol_id, false);
#endif // NBN_USE_HTTPS
server = NBN_GameClient_CreateServerConnection(NULL);
nbn_wrtc_server = NBN_GameClient_CreateServerConnection(NBN_WEBRTC_DRIVER_ID, NULL);
int res;
@@ -400,12 +406,12 @@ int NBN_Driver_GCli_Start(uint32_t protocol_id, const char *host, uint16_t port)
return 0;
}
void NBN_Driver_GCli_Stop(void)
static void NBN_WebRTC_CliStop(void)
{
__js_game_client_close();
}
int NBN_Driver_GCli_RecvPackets(void)
static int NBN_WebRTC_CliRecvPackets(void)
{
uint8_t *data;
unsigned int len;
@@ -414,27 +420,53 @@ int NBN_Driver_GCli_RecvPackets(void)
{
NBN_Packet packet;
if (NBN_Packet_InitRead(&packet, server, data, len) < 0)
if (NBN_Packet_InitRead(&packet, nbn_wrtc_server, data, len) < 0)
continue;
if (!is_connected_to_server)
{
NBN_Driver_GCli_RaiseEvent(NBN_DRIVER_GCLI_CONNECTED, NULL);
NBN_Driver_RaiseEvent(NBN_DRIVER_CLI_CONNECTED, NULL);
is_connected_to_server = true;
}
NBN_Driver_GCli_RaiseEvent(NBN_DRIVER_GCLI_SERVER_PACKET_RECEIVED, &packet);
NBN_Driver_RaiseEvent(NBN_DRIVER_CLI_PACKET_RECEIVED, &packet);
}
return 0;
}
int NBN_Driver_GCli_SendPacket(NBN_Packet *packet)
static int NBN_WebRTC_CliSendPacket(NBN_Packet *packet)
{
return __js_game_client_send_packet(packet->buffer, packet->size);
}
#pragma endregion /* Game client */
#pragma region Driver registering
void NBN_WebRTC_Register(void)
{
NBN_Driver_Register(
NBN_WEBRTC_DRIVER_ID,
NBN_WEBRTC_DRIVER_NAME,
(NBN_DriverImplementation){
// Client implementation
NBN_WebRTC_CliStart,
NBN_WebRTC_CliStop,
NBN_WebRTC_CliRecvPackets,
NBN_WebRTC_CliSendPacket,
// Server implementation
NBN_WebRTC_ServStart,
NBN_WebRTC_ServStop,
NBN_WebRTC_ServRecvPackets,
NBN_WebRTC_ServSendPacketTo,
NBN_WebRTC_ServRemoveClientConnection
}
);
}
#pragma endregion /* Driver registering */
#endif /* NBNET_IMPL */
+5 -1
View File
@@ -99,7 +99,11 @@ function handleConnection(gameServer, connection) {
}
peer.onPacketReceived = (packet) => {
gameServer.packets.push([packet, peer.id])
if (gameServer.onPacketReceived) {
gameServer.onPacketReceived(packet, peer.id)
} else {
gameServer.packets.push([packet, peer.id])
}
}
gameServer.logger.info('Created new peer (id: %d) for connection %d', peer.id, connection.id)
@@ -16,7 +16,7 @@ SignalingClient.prototype.connect = function(host, port) {
const WebSocket = require('websocket').w3cwebsocket
this.ws = new WebSocket(uri, this.protocol)
this.ws = new WebSocket(uri)
this.ws.onclose = (ev) => {
if (this.connected) {
@@ -0,0 +1,104 @@
/*
Copyright (C) 2022 BIAGINI Nathan
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
const unix = require('unix-dgram')
const nbnet = require('../index.js')
const loggerFactory = require('../logger.js')
const IPC_PACKET_HEADER_SIZE = 4
function usage() {
console.log('Usage: node webrtc-ipc_proxy.js PROTOCOL_ID PORT SOCK_PATH')
}
function buildProtocolId(protocol_name) {
/*let protocol_id = 2166136261
for (let i = 0; i < protocol_name.length; i++)
{
protocol_id *= 16777619
protocol_id ^= protocol_name[i]
}
return protocol_id*/
return 42
}
function sendPacket(sockPath, peerId, data) {
let buffer = Buffer.from(data)
let packetData = Buffer.alloc(IPC_PACKET_HEADER_SIZE + buffer.length)
packetData.writeUInt32BE(peerId)
buffer.copy(packetData, IPC_PACKET_HEADER_SIZE)
clientSocket.sendto(packetData, 0, packetData.length, sockPath)
}
const logger = loggerFactory.createLogger('webrtc-ipc_proxy')
const args = process.argv.slice(2)
if (args.length < 3)
{
usage()
process.exit(1)
}
const protocol_id = buildProtocolId(args[0])
const port = args[1]
const sockPath = args[2]
const useHttps = false // TODO: read from command line
const signalingServer = new nbnet.Standalone.SignalingServer(
protocol_id,
useHttps ? { https: true, key: UTF8ToString(keyPem), cert: UTF8ToString(certPem) } : {}
)
const gameServer = new nbnet.GameServer(signalingServer)
const serverSocket = unix.createSocket('unix_dgram', (buffer) => {
console.log('PACKET RECEIVED FROM NBNET')
let peerId = buffer.readUInt32BE()
let data = buffer.subarray(IPC_PACKET_HEADER_SIZE)
gameServer.send(data, peerId)
})
const clientSocket = unix.createSocket('unix_dgram')
serverSocket.on('error', (err) => {
logger.error(err)
process.exit(1)
})
clientSocket.on('error', (err) => {
logger.error(err)
process.exit(1)
})
serverSocket.on('listening', () => {
logger.info('Started listening on UNIX socket (path: %s)...', sockPath)
})
gameServer.onPacketReceived = (packet, peerId) => {
// logger.info('PACKET RECEIVED FROM WEBRTC: %d %d', packet.byteLength, peerId)
sendPacket(sockPath, peerId, packet)
}
serverSocket.bind(sockPath)
gameServer.start(port)
Submodule net_drivers/webrtc/js/webrtc-ipc_proxy/node-unix-dgram added at 33b4fa384f.
+856
View File
@@ -0,0 +1,856 @@
{
"name": "webrtc-ipc_proxy",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@colors/colors": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
"integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="
},
"@dabh/diagnostics": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
"integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
"requires": {
"colorspace": "1.1.x",
"enabled": "2.0.x",
"kuler": "^2.0.0"
}
},
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
},
"aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
},
"are-we-there-yet": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
"integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
"requires": {
"delegates": "^1.0.0",
"readable-stream": "^2.0.6"
},
"dependencies": {
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"async": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"bufferutil": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz",
"integrity": "sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==",
"requires": {
"node-gyp-build": "^4.3.0"
}
},
"chownr": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
},
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA=="
},
"color": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
"integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
"requires": {
"color-convert": "^1.9.3",
"color-string": "^1.6.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
"color-string": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"colorspace": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
"integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
"requires": {
"color": "^3.1.3",
"text-hex": "1.0.x"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
},
"core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"d": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
"integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
"requires": {
"es5-ext": "^0.10.50",
"type": "^1.0.1"
}
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
},
"detect-libc": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="
},
"domexception": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
"integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==",
"optional": true,
"requires": {
"webidl-conversions": "^4.0.2"
}
},
"enabled": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
"integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
},
"es5-ext": {
"version": "0.10.62",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
"integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
"requires": {
"es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.3",
"next-tick": "^1.1.0"
}
},
"es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
"requires": {
"d": "1",
"es5-ext": "^0.10.35",
"es6-symbol": "^3.1.1"
}
},
"es6-symbol": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
"integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
"requires": {
"d": "^1.0.1",
"ext": "^1.1.2"
}
},
"ext": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
"integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
"requires": {
"type": "^2.7.2"
},
"dependencies": {
"type": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
"integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw=="
}
}
},
"fecha": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
"integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="
},
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
"fn.name": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"fs-minipass": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
"integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
"requires": {
"minipass": "^2.6.0"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
"requires": {
"aproba": "^1.0.3",
"console-control-strings": "^1.0.0",
"has-unicode": "^2.0.0",
"object-assign": "^4.1.0",
"signal-exit": "^3.0.0",
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wide-align": "^1.1.0"
}
},
"glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ignore-walk": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz",
"integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==",
"requires": {
"minimatch": "^3.0.4"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
"requires": {
"number-is-nan": "^1.0.0"
}
},
"is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"kuler": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
},
"logform": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/logform/-/logform-2.4.2.tgz",
"integrity": "sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw==",
"requires": {
"@colors/colors": "1.5.0",
"fecha": "^4.2.0",
"ms": "^2.1.1",
"safe-stable-stringify": "^2.3.1",
"triple-beam": "^1.3.0"
},
"dependencies": {
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}
}
},
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g=="
},
"minipass": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
"integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
}
},
"minizlib": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
"integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
"requires": {
"minipass": "^2.9.0"
}
},
"mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"requires": {
"minimist": "^1.2.6"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"nan": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ=="
},
"needle": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz",
"integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==",
"requires": {
"debug": "^3.2.6",
"iconv-lite": "^0.4.4",
"sax": "^1.2.4"
},
"dependencies": {
"debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}
}
},
"next-tick": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
},
"node-gyp-build": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz",
"integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg=="
},
"node-pre-gyp": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz",
"integrity": "sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ==",
"requires": {
"detect-libc": "^1.0.2",
"mkdirp": "^0.5.1",
"needle": "^2.2.1",
"nopt": "^4.0.1",
"npm-packlist": "^1.1.6",
"npmlog": "^4.0.2",
"rc": "^1.2.7",
"rimraf": "^2.6.1",
"semver": "^5.3.0",
"tar": "^4"
}
},
"nopt": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
"integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
"requires": {
"abbrev": "1",
"osenv": "^0.1.4"
}
},
"npm-bundled": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz",
"integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==",
"requires": {
"npm-normalize-package-bin": "^1.0.1"
}
},
"npm-normalize-package-bin": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
"integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
},
"npm-packlist": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
"integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
"requires": {
"ignore-walk": "^3.0.1",
"npm-bundled": "^1.0.1",
"npm-normalize-package-bin": "^1.0.1"
}
},
"npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"requires": {
"are-we-there-yet": "~1.1.2",
"console-control-strings": "~1.1.0",
"gauge": "~2.7.3",
"set-blocking": "~2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ=="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"requires": {
"wrappy": "1"
}
},
"one-time": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
"integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
"requires": {
"fn.name": "1.x.x"
}
},
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ=="
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="
},
"osenv": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
"requires": {
"os-homedir": "^1.0.0",
"os-tmpdir": "^1.0.0"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"requires": {
"deep-extend": "^0.6.0",
"ini": "~1.3.0",
"minimist": "^1.2.0",
"strip-json-comments": "~2.0.1"
}
},
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
},
"rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"requires": {
"glob": "^7.1.3"
}
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"safe-stable-stringify": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz",
"integrity": "sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
},
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
},
"signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"requires": {
"is-arrayish": "^0.3.1"
}
},
"stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
"integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==",
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
}
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"requires": {
"ansi-regex": "^2.0.0"
}
},
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="
},
"tar": {
"version": "4.4.19",
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz",
"integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==",
"requires": {
"chownr": "^1.1.4",
"fs-minipass": "^1.2.7",
"minipass": "^2.9.0",
"minizlib": "^1.3.3",
"mkdirp": "^0.5.5",
"safe-buffer": "^5.2.1",
"yallist": "^3.1.1"
}
},
"text-hex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
},
"triple-beam": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
"integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
},
"type": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
},
"typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
"requires": {
"is-typedarray": "^1.0.0"
}
},
"unix-dgram": {
"version": "file:node-unix-dgram",
"requires": {
"bindings": "^1.5.0",
"nan": "^2.16.0"
}
},
"utf-8-validate": {
"version": "5.0.10",
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
"integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
"requires": {
"node-gyp-build": "^4.3.0"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"webidl-conversions": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
"optional": true
},
"websocket": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz",
"integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==",
"requires": {
"bufferutil": "^4.0.1",
"debug": "^2.2.0",
"es5-ext": "^0.10.50",
"typedarray-to-buffer": "^3.1.5",
"utf-8-validate": "^5.0.2",
"yaeti": "^0.0.6"
}
},
"wide-align": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
"requires": {
"string-width": "^1.0.2 || 2 || 3 || 4"
}
},
"winston": {
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz",
"integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==",
"requires": {
"@colors/colors": "1.5.0",
"@dabh/diagnostics": "^2.0.2",
"async": "^3.2.3",
"is-stream": "^2.0.0",
"logform": "^2.4.0",
"one-time": "^1.0.0",
"readable-stream": "^3.4.0",
"safe-stable-stringify": "^2.3.1",
"stack-trace": "0.0.x",
"triple-beam": "^1.3.0",
"winston-transport": "^4.5.0"
}
},
"winston-transport": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz",
"integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==",
"requires": {
"logform": "^2.3.2",
"readable-stream": "^3.6.0",
"triple-beam": "^1.3.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"wrtc": {
"version": "0.4.7",
"resolved": "https://registry.npmjs.org/wrtc/-/wrtc-0.4.7.tgz",
"integrity": "sha512-P6Hn7VT4lfSH49HxLHcHhDq+aFf/jd9dPY7lDHeFhZ22N3858EKuwm2jmnlPzpsRGEPaoF6XwkcxY5SYnt4f/g==",
"requires": {
"domexception": "^1.0.1",
"node-pre-gyp": "^0.13.0"
}
},
"yaeti": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
"integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug=="
},
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
}
@@ -0,0 +1,17 @@
{
"name": "webrtc-ipc_proxy",
"version": "0.0.1",
"description": "WebRTC to IPC proxy to use with nbnet IPC driver",
"author": "BIAGINI Nathan",
"license": "MIT",
"main": "js/index.js",
"dependencies": {
"unix-dgram": "./node-unix-dgram",
"websocket": "^1.0.31",
"winston": "^3.2.1",
"wrtc": "^0.4.2"
},
"scripts": {
"start": "node index.js"
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "nbnet",
"version": "0.0.1",
"version": "1.0",
"description": "WebRTC driver for the nbnet library",
"author": "BIAGINI Nathan",
"license": "MIT",
+534
View File
@@ -0,0 +1,534 @@
/*
Copyright (C) 2022 BIAGINI Nathan
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
--- NBNET C (NATIVE) WEBRTC DRIVER ---
WebRTC driver using a single unreliable data channel for the nbnet library. The difference between
this driver and the other "WebRTC" one (webrtc.h) is that it's fully written in C (no JavaScript).
Dependencies:
1. facil.io (websockets)
2. libdatachannel (WebRTC data channels)
3. json.h (https://github.com/sheredom/json.h)
How to use:
1. Include this header *once* after the nbnet header in the same file where you defined the NBNET_IMPL macro
2. Call NBN_WebRTC_C_Register in both your client and server code before calling NBN_GameClient_Start or NBN_GameServer_Start
*/
#include <http.h>
#include <rtc/rtc.h>
#include "json.h"
#define NBN_WEBRTC_C_DRIVER_ID 2
#define NBN_WEBRTC_C_DRIVER_NAME "WebRTC_C"
void NBN_WebRTC_C_Register(void);
#ifdef NBNET_IMPL
typedef struct
{
int id;
int channel_id;
ws_s *ws;
} NBN_WebRTC_C_Peer;
#pragma region Hashtable
#define HTABLE_DEFAULT_INITIAL_CAPACITY 32
#define HTABLE_LOAD_FACTOR_THRESHOLD 0.75
typedef struct
{
int peer_id;
NBN_WebRTC_C_Peer *peer;
unsigned int slot;
} NBN_WebRTC_C_HTableEntry;
typedef struct
{
NBN_WebRTC_C_HTableEntry **internal_array;
unsigned int capacity;
unsigned int count;
float load_factor;
} NBN_WebRTC_C_HTable;
static NBN_WebRTC_C_HTable *NBN_WebRTC_C_HTable_Create(void);
static NBN_WebRTC_C_HTable *NBN_WebRTC_C_HTable_CreateWithCapacity(unsigned int);
static void NBN_WebRTC_C_HTable_Destroy(NBN_WebRTC_C_HTable *);
static void NBN_WebRTC_C_HTable_Add(NBN_WebRTC_C_HTable *, int, NBN_WebRTC_C_Peer *);
static NBN_WebRTC_C_Peer *NBN_WebRTC_C_HTable_Get(NBN_WebRTC_C_HTable *, int);
static NBN_WebRTC_C_Peer *NBN_WebRTC_C_HTable_Remove(NBN_WebRTC_C_HTable *, int);
static void NBN_WebRTC_C_HTable_InsertEntry(NBN_WebRTC_C_HTable *, NBN_WebRTC_C_HTableEntry *);
static void NBN_WebRTC_C_HTable_RemoveEntry(NBN_WebRTC_C_HTable *, NBN_WebRTC_C_HTableEntry *);
static unsigned int NBN_WebRTC_C_HTable_FindFreeSlot(NBN_WebRTC_C_HTable *, NBN_WebRTC_C_HTableEntry *, bool *);
static NBN_WebRTC_C_HTableEntry *NBN_WebRTC_C_HTable_FindEntry(NBN_WebRTC_C_HTable *, int);
static void NBN_WebRTC_C_HTable_Grow(NBN_WebRTC_C_HTable *);
static NBN_WebRTC_C_HTable *NBN_WebRTC_C_HTable_Create(void)
{
return NBN_WebRTC_C_HTable_CreateWithCapacity(HTABLE_DEFAULT_INITIAL_CAPACITY);
}
static NBN_WebRTC_C_HTable *NBN_WebRTC_C_HTable_CreateWithCapacity(unsigned int capacity)
{
NBN_WebRTC_C_HTable *htable = NBN_Allocator(sizeof(NBN_WebRTC_C_HTable));
htable->internal_array = NBN_Allocator(sizeof(NBN_WebRTC_C_HTableEntry *) * capacity);
htable->capacity = capacity;
htable->count = 0;
htable->load_factor = 0;
for (unsigned int i = 0; i < htable->capacity; i++)
htable->internal_array[i] = NULL;
return htable;
}
static void NBN_WebRTC_C_HTable_Destroy(NBN_WebRTC_C_HTable *htable)
{
for (unsigned int i = 0; i < htable->capacity; i++)
{
NBN_WebRTC_C_HTableEntry *entry = htable->internal_array[i];
if (entry)
NBN_Deallocator(entry);
}
NBN_Deallocator(htable->internal_array);
NBN_Deallocator(htable);
}
static void NBN_WebRTC_C_HTable_Add(NBN_WebRTC_C_HTable *htable, int peer_id, NBN_WebRTC_C_Peer *peer)
{
NBN_WebRTC_C_HTableEntry *entry = NBN_Allocator(sizeof(NBN_WebRTC_C_HTableEntry));
entry->peer_id = peer_id;
entry->peer = peer;
NBN_WebRTC_C_HTable_InsertEntry(htable, entry);
if (htable->load_factor >= HTABLE_LOAD_FACTOR_THRESHOLD)
NBN_WebRTC_C_HTable_Grow(htable);
}
static NBN_WebRTC_C_Peer *NBN_WebRTC_C_HTable_Get(NBN_WebRTC_C_HTable *htable, int peer_id)
{
NBN_WebRTC_C_HTableEntry *entry = NBN_WebRTC_C_HTable_FindEntry(htable, peer_id);
return entry ? entry->peer : NULL;
}
static NBN_WebRTC_C_Peer *NBN_WebRTC_C_HTable_Remove(NBN_WebRTC_C_HTable *htable, int peer_id)
{
NBN_WebRTC_C_HTableEntry *entry = NBN_WebRTC_C_HTable_FindEntry(htable, peer_id);
if (entry)
{
NBN_WebRTC_C_Peer *peer = entry->peer;
NBN_WebRTC_C_HTable_RemoveEntry(htable, entry);
return peer;
}
return NULL;
}
static void NBN_WebRTC_C_HTable_InsertEntry(NBN_WebRTC_C_HTable *htable, NBN_WebRTC_C_HTableEntry *entry)
{
bool use_existing_slot = false;
unsigned int slot = NBN_WebRTC_C_HTable_FindFreeSlot(htable, entry, &use_existing_slot);
entry->slot = slot;
htable->internal_array[slot] = entry;
if (!use_existing_slot)
{
htable->count++;
htable->load_factor = (float)htable->count / htable->capacity;
}
}
static void NBN_WebRTC_C_HTable_RemoveEntry(NBN_WebRTC_C_HTable *htable, NBN_WebRTC_C_HTableEntry *entry)
{
htable->internal_array[entry->slot] = NULL;
NBN_Deallocator(entry);
htable->count--;
htable->load_factor = htable->count / htable->capacity;
}
static unsigned int NBN_WebRTC_C_HTable_FindFreeSlot(NBN_WebRTC_C_HTable *htable, NBN_WebRTC_C_HTableEntry *entry, bool *use_existing_slot)
{
unsigned long hash = entry->peer_id;
unsigned int slot;
// quadratic probing
NBN_WebRTC_C_HTableEntry *current_entry;
unsigned int i = 0;
do
{
slot = (hash + (int)pow(i, 2)) % htable->capacity;
current_entry = htable->internal_array[slot];
i++;
} while (current_entry != NULL && current_entry->peer_id != entry->peer_id);
if (current_entry != NULL) // it means the current entry as the same key as the inserted entry
{
*use_existing_slot = true;
NBN_Deallocator(current_entry);
}
return slot;
}
static NBN_WebRTC_C_HTableEntry *NBN_WebRTC_C_HTable_FindEntry(NBN_WebRTC_C_HTable *htable, int peer_id)
{
unsigned long hash = peer_id;
unsigned int slot;
//quadratic probing
NBN_WebRTC_C_HTableEntry *current_entry;
unsigned int i = 0;
do
{
slot = (hash + (int)pow(i, 2)) % htable->capacity;
current_entry = htable->internal_array[slot];
if (current_entry != NULL && current_entry->peer_id == peer_id)
{
return current_entry;
}
i++;
} while (i < htable->capacity);
return NULL;
}
static void NBN_WebRTC_C_HTable_Grow(NBN_WebRTC_C_HTable *htable)
{
unsigned int old_capacity = htable->capacity;
unsigned int new_capacity = old_capacity * 2;
NBN_WebRTC_C_HTableEntry** old_internal_array = htable->internal_array;
NBN_WebRTC_C_HTableEntry** new_internal_array = NBN_Allocator(sizeof(NBN_WebRTC_C_HTableEntry*) * new_capacity);
for (unsigned int i = 0; i < new_capacity; i++)
{
new_internal_array[i] = NULL;
}
htable->internal_array = new_internal_array;
htable->capacity = new_capacity;
htable->count = 0;
htable->load_factor = 0;
// rehash
for (unsigned int i = 0; i < old_capacity; i++)
{
if (old_internal_array[i])
NBN_WebRTC_C_HTable_InsertEntry(htable, old_internal_array[i]);
}
NBN_Deallocator(old_internal_array);
}
#pragma endregion // Hashtable
#pragma Signaling
typedef enum
{
NBN_WEBRTC_C_UNDEFINED,
NBN_WEBRTC_C_OFFER
} NBN_WebRTC_C_SignalingPayloadType;
typedef struct
{
NBN_WebRTC_C_SignalingPayloadType type;
const char *sdp;
struct json_value_s *json;
} NBN_WebRTC_C_SignalingPayload;
static bool NBN_WebRTC_C_ParseSignalingMessage(const char *msg, size_t msg_len, NBN_WebRTC_C_SignalingPayload *payload)
{
struct json_value_s* root = json_parse(msg, msg_len);
if (root->type != json_type_object)
{
free(root);
return false;
}
struct json_object_s* object = (struct json_object_s*)root->payload;
struct json_object_element_s *curr = object->start;
payload->json = root;
payload->type = NBN_WEBRTC_C_UNDEFINED;
payload->sdp = NULL;
while (curr != NULL)
{
if (strncmp(curr->name->string, "type", 4) == 0)
{
payload->type = NBN_WEBRTC_C_OFFER;
}
else if (strncmp(curr->name->string, "sdp", 4) == 0)
{
struct json_string_s *str = json_value_as_string(curr->value);
if (str)
{
payload->sdp = str->string;
}
}
curr = curr->next;
}
if (payload->type == NBN_WEBRTC_C_UNDEFINED)
{
free(root);
return false;
}
return true;
}
static void NBN_WebRTC_C_OnLocalDescriptionCallback(int pc, const char *sdp, const char *type, void *user_ptr)
{
if (strncmp(type, "answer", 5) != 0) return;
ws_s *ws = user_ptr;
fio_str_info_s msg;
char data[1024];
snprintf(data, sizeof(data), "{\"type\":\"answer\", \"data\":\"%s\"}", sdp);
msg.data = data;
msg.len = strnlen(data, sizeof(data));
NBN_LogDebug("SDP: %s", sdp);
websocket_write(ws, msg, 1);
}
#pragma endregion /* Signaling */
#pragma region Game server
static const char *ice_servers[] = {
"stun:stun01.sipphone.com"
};
static NBN_WebRTC_C_HTable *nbn_wrtc_c_peers = NULL;
static void NBN_WebRTC_C_DestroyPeer(NBN_WebRTC_C_Peer *peer)
{
NBN_WebRTC_C_HTable_Remove(nbn_wrtc_c_peers, peer->id);
NBN_Deallocator(peer);
}
static void on_websocket_open(ws_s *ws)
{
int peer_id = rtcCreatePeerConnection(&(rtcConfiguration){
.iceServers = ice_servers,
.iceServersCount = 1,
.disableAutoNegotiation = false
});
if (peer_id < 0)
{
NBN_LogError("Failed to create peer: %d", peer_id);
return;
}
// save a pointer to the WS in peer's user data
rtcSetUserPointer(peer_id, ws);
int ret = rtcSetLocalDescriptionCallback(peer_id, NBN_WebRTC_C_OnLocalDescriptionCallback);
if (ret < 0)
{
NBN_LogError("Failed to register local description callback for peer %d: %d", peer_id, ret);
rtcDeletePeerConnection(peer_id);
}
int channel_id = rtcCreateDataChannelEx(peer_id, "unreliable", &(rtcDataChannelInit){
.reliability = {.unordered = true, .unreliable = true, .maxPacketLifeTime = 1000, .maxRetransmits = 0},
.negotiated = true,
.manualStream = true,
.stream = 0
});
if (channel_id < 0)
{
NBN_LogError("Failed to create data channel for peer %d: %d", peer_id, channel_id);
rtcDeletePeerConnection(peer_id);
}
NBN_LogDebug("Successfully created data channel for peer %d", peer_id);
NBN_WebRTC_C_Peer *peer = (NBN_WebRTC_C_Peer *)NBN_Allocator(sizeof(NBN_WebRTC_C_Peer));
peer->id = peer_id;
peer->channel_id = channel_id;
peer->ws = ws;
// save a pointer to the peer in websocket's user data
websocket_udata_set(ws, peer);
NBN_WebRTC_C_HTable_Add(nbn_wrtc_c_peers, peer_id, peer);
}
static void on_websocket_close(intptr_t uuid, void *udata)
{
if (uuid >= 0 && udata)
{
NBN_LogDebug("ON CLOSE: %p", udata);
}
}
static void on_websocket_message(ws_s *ws, fio_str_info_s msg, uint8_t is_text)
{
NBN_LogDebug("RECEIVED: %s", msg.data);
NBN_WebRTC_C_SignalingPayload payload;
bool ret = NBN_WebRTC_C_ParseSignalingMessage(msg.data, msg.len, &payload);
if (!ret) return;
if (payload.type == NBN_WEBRTC_C_OFFER && payload.sdp)
{
NBN_WebRTC_C_Peer *peer = websocket_udata_get(ws);
int ret = rtcSetRemoteDescription(peer->id, payload.sdp, "offer");
if (ret < 0)
{
NBN_LogError("Failed to set remote description for peer %d: %d", peer->id, ret);
}
}
free(payload.json);
}
static void on_http_request(http_s *request)
{
const char *msg = "This is a websocket server\n";
http_set_header(request, HTTP_HEADER_CONTENT_TYPE, http_mimetype_find("txt", 3));
http_send_body(request, (void *)msg, strlen(msg));
}
static void on_http_upgrade(http_s *request, char *target, size_t len)
{
if (len >= 9 && target[1] == 'e')
{
http_upgrade2ws(
request,
.on_message = on_websocket_message,
.on_open = on_websocket_open,
.on_close = on_websocket_close);
}
else if (len >= 3 && target[0] == 's')
{
http_upgrade2sse(request, .on_open = NULL);
}
else
{
http_send_error(request, 400);
}
}
static int NBN_WebRTC_C_ServStart(uint32_t protocol_id, uint16_t port)
{
// protocol_id is not use with this driver
nbn_wrtc_c_peers = NBN_WebRTC_C_HTable_Create();
if (http_listen("42043", NULL, .on_request = on_http_request, .on_upgrade = on_http_upgrade) < 0)
{
NBN_LogError("Failed to start websocket server");
return -1;
}
fio_start(.threads = 1);
return 0;
}
static void NBN_WebRTC_C_ServStop(void)
{
NBN_WebRTC_C_HTable_Destroy(nbn_wrtc_c_peers);
}
static int NBN_WebRTC_C_ServRecvPackets(void)
{
return 0;
}
static void NBN_WebRTC_C_ServRemoveClientConnection(NBN_Connection *conn)
{
}
static int NBN_WebRTC_C_ServSendPacketTo(NBN_Packet *packet, NBN_Connection *conn)
{
return 0;
}
#pragma endregion /* Game server */
void NBN_WebRTC_C_Register(void)
{
NBN_Driver_Register(
NBN_WEBRTC_C_DRIVER_ID,
NBN_WEBRTC_C_DRIVER_NAME,
(NBN_DriverImplementation){
// Client implementation
NULL,
NULL,
NULL,
NULL,
// Server implementation
NBN_WebRTC_C_ServStart,
NBN_WebRTC_C_ServStop,
NBN_WebRTC_C_ServRecvPackets,
NBN_WebRTC_C_ServSendPacketTo,
NBN_WebRTC_C_ServRemoveClientConnection});
}
#endif // NBNET_IMPL
+17
View File
@@ -21,6 +21,7 @@ target_compile_definitions(client PUBLIC NBN_DEBUG NBN_DISABLE_STALE_CONNECTION_
target_compile_definitions(server PUBLIC NBN_DEBUG NBN_DISABLE_STALE_CONNECTION_DETECTION NBN_USE_PACKET_SIMULATOR SOAK_SERVER)
option(ENCRYPTION_ENABLED OFF)
option(WEBRTC_DRIVER_C OFF)
if (ENCRYPTION_ENABLED)
message("Encryption enabled")
@@ -29,6 +30,22 @@ if (ENCRYPTION_ENABLED)
target_compile_definitions(server PUBLIC SOAK_ENCRYPTION)
endif(ENCRYPTION_ENABLED)
# compile with C WebRTC driver
if (WEBRTC_C_DRIVER)
message("Compiling with C WebRTC driver")
target_compile_definitions(server PUBLIC SOAK_WEBRTC_C_DRIVER)
target_link_libraries(server ${LIBFACILIO_LIBRARY_PATH})
target_link_libraries(server ${LIBCRYPTO_LIBRARY_PATH})
target_link_libraries(server ${LIBSSL_LIBRARY_PATH})
target_link_libraries(server ${LIBDATACHANNEL_LIBRARY_PATH})
target_include_directories(server PUBLIC "${LIBFACILIO_INCLUDE_PATH}")
target_include_directories(server PUBLIC "${OPENSSL_INCLUDE_PATH}")
target_include_directories(server PUBLIC "${LIBDATACHANNEL_INCLUDE_PATH}")
endif (WEBRTC_C_DRIVER)
unset(ENCRYPTION_ENABLED)
if(WIN32)
+6
View File
@@ -240,6 +240,12 @@ int main(int argc, char *argv[])
{
Soak_SetLogLevel(LOG_TRACE);
#ifdef __EMSCRIPTEN__
NBN_WebRTC_Register(); // Register the WebRTC driver
#else
NBN_UDP_Register(); // Register the UDP driver
#endif // __EMSCRIPTEN__
if (NBN_GameClient_Start(SOAK_PROTOCOL_NAME, "127.0.0.1", SOAK_PORT, false, NULL) < 0)
{
Soak_LogError("Failed to start game client. Exit");
+21 -1
View File
@@ -35,7 +35,14 @@
#else
/* Use UDP driver */
#include "../net_drivers/udp.h"
#endif
#ifdef SOAK_WEBRTC_C_DRIVER
#include "../net_drivers/webrtc_c.h"
#endif // SOAK_WEBRTC_C_DRIVER
#endif // __EMSCRIPTEN__
typedef struct
{
@@ -266,6 +273,19 @@ int main(int argc, char *argv[])
Soak_SetLogLevel(LOG_TRACE);
#ifdef __EMSCRIPTEN__
NBN_WebRTC_Register(); // Register the WebRTC driver
#else
NBN_UDP_Register(); // Register the UDP driver
#ifdef SOAK_WEBRTC_C_DRIVER
NBN_WebRTC_C_Register(); // Register native WebRTC driver
#endif // SOAK_WEBRTC_C_DRIVER
#endif // __EMSCRIPTEN__
if (NBN_GameServer_Start(SOAK_PROTOCOL_NAME, SOAK_PORT, false))
{
Soak_LogError("Failed to start game server");