mirror of
https://github.com/bdnugget/nbnet.git
synced 2026-11-07 05:27:27 +00:00
WIP
This commit is contained in:
1 parent
21a839587c
commit
6f75b3b807
24 files changed
+5993
-271
No files matched your search
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
+120
-88
@@ -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
@@ -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 */
|
||||
@@ -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.
@@ -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,6 +1,6 @@
|
||||
{
|
||||
"name": "nbnet",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0",
|
||||
"description": "WebRTC driver for the nbnet library",
|
||||
"author": "BIAGINI Nathan",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
Reference in new issue
Block a user