net wake sockets
This commit is contained in:
parent
9912e0bfdd
commit
d9451af62e
@ -250,6 +250,7 @@
|
|||||||
|
|
||||||
//- Time
|
//- Time
|
||||||
#define NsFromSeconds(s) ((i64)((s) * 1000000000.0))
|
#define NsFromSeconds(s) ((i64)((s) * 1000000000.0))
|
||||||
|
#define MsFromNs(ns) ((f64)((ns) / 1000000.0))
|
||||||
#define SecondsFromNs(ns) ((f64)(ns) / 1000000000.0)
|
#define SecondsFromNs(ns) ((f64)(ns) / 1000000000.0)
|
||||||
|
|
||||||
//- Busy-wait
|
//- Busy-wait
|
||||||
|
|||||||
@ -6,18 +6,68 @@ NET_W32_Ctx NET_W32 = Zi;
|
|||||||
void NET_Bootstrap(void)
|
void NET_Bootstrap(void)
|
||||||
{
|
{
|
||||||
Arena *perm = PermArena();
|
Arena *perm = PermArena();
|
||||||
|
|
||||||
|
// Init winsock
|
||||||
WSADATA wsa = Zi;
|
WSADATA wsa = Zi;
|
||||||
i32 err = WSAStartup(MAKEWORD(2,2), &wsa);
|
i32 err = WSAStartup(MAKEWORD(2,2), &wsa);
|
||||||
if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
|
if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
|
||||||
{
|
{
|
||||||
Panic(StringF(perm, "Failed to initialize WinSock (error code - %F)", FmtSint(err)));
|
Panic(StringF(perm, "Failed to initialize Winsock (error code - %F)", FmtSint(err)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init worker wake sockets
|
||||||
|
NET_W32.wake_send_sock = NET_W32_CreateDummySocket();
|
||||||
|
NET_W32.wake_recv_sock = NET_W32_CreateDummySocket();
|
||||||
|
|
||||||
|
// Start worker
|
||||||
DispatchWave(Lit("Net"), 1, NET_W32_TickForever, 0);
|
DispatchWave(Lit("Net"), 1, NET_W32_TickForever, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Helpers
|
//~ Helpers
|
||||||
|
|
||||||
|
NET_W32_DummySocket NET_W32_CreateDummySocket(void)
|
||||||
|
{
|
||||||
|
NET_W32_DummySocket result = Zi;
|
||||||
|
b32 ok = 1;
|
||||||
|
SOCKET sock = 0;
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
ok = sock != INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
struct sockaddr_in addr = Zi;
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
ok = bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0;
|
||||||
|
}
|
||||||
|
struct sockaddr_storage ss = Zi;
|
||||||
|
i32 ss_sizeof = sizeof(ss);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
ok = getsockname(sock, (struct sockaddr *)&ss, &ss_sizeof) != SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
u_long nonblocking = 1;
|
||||||
|
ok = ioctlsocket(sock, FIONBIO, &nonblocking) == 0;
|
||||||
|
}
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
if (sock != INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
closesocket(sock);
|
||||||
|
sock = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.sock = sock;
|
||||||
|
result.addr_size = ss_sizeof;
|
||||||
|
result.addr = ss;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
NET_W32_Pipe *NET_W32_PipeFromHandle(NET_PipeHandle pipe_handle)
|
NET_W32_Pipe *NET_W32_PipeFromHandle(NET_PipeHandle pipe_handle)
|
||||||
{
|
{
|
||||||
return (NET_W32_Pipe *)pipe_handle.v;
|
return (NET_W32_Pipe *)pipe_handle.v;
|
||||||
@ -45,7 +95,21 @@ u64 NET_W32_HashFromKey(NET_Key key)
|
|||||||
|
|
||||||
void NET_W32_SignalWorker(void)
|
void NET_W32_SignalWorker(void)
|
||||||
{
|
{
|
||||||
// TODO
|
i32 err = sendto(
|
||||||
|
NET_W32.wake_send_sock.sock,
|
||||||
|
(char *)"1",
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
(struct sockaddr *)&NET_W32.wake_recv_sock.addr,
|
||||||
|
NET_W32.wake_send_sock.addr_size
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
i32 wsa_err = WSAGetLastError();
|
||||||
|
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NET_W32_Peer *NET_W32_TouchPeerFromKey(NET_W32_Pipe *pipe, NET_Key key)
|
NET_W32_Peer *NET_W32_TouchPeerFromKey(NET_W32_Pipe *pipe, NET_Key key)
|
||||||
@ -118,6 +182,7 @@ NET_PipeHandle NET_AcquirePipe(void)
|
|||||||
}
|
}
|
||||||
UnlockTicketMutex(&NET_W32.pipes_tm);
|
UnlockTicketMutex(&NET_W32.pipes_tm);
|
||||||
}
|
}
|
||||||
|
NET_W32_SignalWorker();
|
||||||
return (NET_PipeHandle) { .v = (u64) pipe };
|
return (NET_PipeHandle) { .v = (u64) pipe };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +197,7 @@ void NET_Bind(NET_PipeHandle pipe_handle, u64 port)
|
|||||||
{
|
{
|
||||||
Atomic64Set(&pipe->desired_port, port);
|
Atomic64Set(&pipe->desired_port, port);
|
||||||
}
|
}
|
||||||
|
// FIXME: Signal here if ports don't match
|
||||||
}
|
}
|
||||||
|
|
||||||
NET_Key NET_KeyFromString(String host, String port)
|
NET_Key NET_KeyFromString(String host, String port)
|
||||||
@ -215,16 +281,75 @@ void NET_W32_TickForever(WaveLaneCtx *lane)
|
|||||||
{
|
{
|
||||||
Arena *perm = PermArena();
|
Arena *perm = PermArena();
|
||||||
|
|
||||||
|
i64 seen_signal = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
u32 magic = 0xde8c590b;
|
u32 magic = 0xde8c590b;
|
||||||
i64 heartbeat_threshold_ns = NsFromSeconds(0.250);
|
i64 heartbeat_threshold_ns = NsFromSeconds(0.250);
|
||||||
|
i64 passive_run_threshold_ns = NsFromSeconds(0.250);
|
||||||
// TODO: Block until send/recv/signal
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Pop pipes
|
//- Wait
|
||||||
|
|
||||||
|
{
|
||||||
|
// Build fd list containing every bound pipe's socket + the worker's signal socket
|
||||||
|
i64 fds_count = 0;
|
||||||
|
WSAPOLLFD *fds = 0;
|
||||||
|
{
|
||||||
|
LockTicketMutex(&NET_W32.pipes_tm);
|
||||||
|
{
|
||||||
|
for (NET_W32_Pipe *pipe = NET_W32.first_pipe; pipe; pipe = pipe->next)
|
||||||
|
{
|
||||||
|
if (pipe->udp)
|
||||||
|
{
|
||||||
|
fds_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NET_W32.wake_recv_sock.sock != 0)
|
||||||
|
{
|
||||||
|
fds_count += 1;
|
||||||
|
}
|
||||||
|
fds = PushStructsNoZero(scratch.arena, WSAPOLLFD, fds_count);
|
||||||
|
{
|
||||||
|
i64 fd_idx = 0;
|
||||||
|
for (NET_W32_Pipe *pipe = NET_W32.first_pipe; pipe; pipe = pipe->next)
|
||||||
|
{
|
||||||
|
if (pipe->udp)
|
||||||
|
{
|
||||||
|
fds[fd_idx].fd = pipe->udp;
|
||||||
|
fds[fd_idx].events = POLLRDNORM;
|
||||||
|
fd_idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NET_W32.wake_recv_sock.sock != 0)
|
||||||
|
{
|
||||||
|
fds[fd_idx].fd = NET_W32.wake_recv_sock.sock;
|
||||||
|
fds[fd_idx].events = POLLRDNORM;
|
||||||
|
fd_idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnlockTicketMutex(&NET_W32.pipes_tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait
|
||||||
|
i32 timeout_ms = MsFromNs(passive_run_threshold_ns);
|
||||||
|
WSAPoll(fds, fds_count, timeout_ms);
|
||||||
|
|
||||||
|
// Drain wake recv sock
|
||||||
|
{
|
||||||
|
i32 len = 0;
|
||||||
|
while (len >= 0)
|
||||||
|
{
|
||||||
|
u8 buff[Kibi(2)];
|
||||||
|
len = recv(NET_W32.wake_recv_sock.sock, (char *)buff, countof(buff), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Process pipes
|
||||||
|
|
||||||
i64 pipes_count = 0;
|
i64 pipes_count = 0;
|
||||||
NET_W32_Pipe **pipes = 0;
|
NET_W32_Pipe **pipes = 0;
|
||||||
@ -433,15 +558,15 @@ void NET_W32_TickForever(WaveLaneCtx *lane)
|
|||||||
src_data.text = buff + sizeof(header);
|
src_data.text = buff + sizeof(header);
|
||||||
src_data.len = len - sizeof(header);
|
src_data.len = len - sizeof(header);
|
||||||
|
|
||||||
// if (!(header.flags & NET_W32_PacketFlag_Heartbeat))
|
if (!(header.flags & NET_W32_PacketFlag_Heartbeat))
|
||||||
// {
|
{
|
||||||
// LogDebugF(
|
LogDebugF(
|
||||||
// "Received msg. packet seq: %F, msg seq: %F, data: \"%F\"",
|
"Received msg. packet seq: %F, msg seq: %F, data: \"%F\"",
|
||||||
// FmtSint(header.seq),
|
FmtSint(header.seq),
|
||||||
// FmtSint(header.msg_seq),
|
FmtSint(header.msg_seq),
|
||||||
// FmtString(src_data)
|
FmtString(src_data)
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
|
|
||||||
//- Fetch peer
|
//- Fetch peer
|
||||||
NET_W32_Peer *peer = NET_W32_TouchPeerFromKey(pipe, key);
|
NET_W32_Peer *peer = NET_W32_TouchPeerFromKey(pipe, key);
|
||||||
@ -786,7 +911,6 @@ void NET_W32_TickForever(WaveLaneCtx *lane)
|
|||||||
if (should_send_heartbeat)
|
if (should_send_heartbeat)
|
||||||
{
|
{
|
||||||
struct sockaddr_in6 addr = NET_W32_AddressFromKey(peer->key);
|
struct sockaddr_in6 addr = NET_W32_AddressFromKey(peer->key);
|
||||||
|
|
||||||
i64 buff_len = 0;
|
i64 buff_len = 0;
|
||||||
u8 buff[Kibi(2)];
|
u8 buff[Kibi(2)];
|
||||||
NET_W32_PacketHeader header = Zi;
|
NET_W32_PacketHeader header = Zi;
|
||||||
|
|||||||
@ -143,6 +143,13 @@ Struct(NET_W32_Pipe)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ State types
|
//~ State types
|
||||||
|
|
||||||
|
Struct(NET_W32_DummySocket)
|
||||||
|
{
|
||||||
|
SOCKET sock;
|
||||||
|
i32 addr_size;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
};
|
||||||
|
|
||||||
Struct(NET_W32_Ctx)
|
Struct(NET_W32_Ctx)
|
||||||
{
|
{
|
||||||
TicketMutex pipes_tm;
|
TicketMutex pipes_tm;
|
||||||
@ -152,6 +159,9 @@ Struct(NET_W32_Ctx)
|
|||||||
|
|
||||||
NET_W32_Peer *first_free_peer;
|
NET_W32_Peer *first_free_peer;
|
||||||
NET_W32_Packet *first_free_packet;
|
NET_W32_Packet *first_free_packet;
|
||||||
|
|
||||||
|
NET_W32_DummySocket wake_send_sock;
|
||||||
|
NET_W32_DummySocket wake_recv_sock;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NET_W32_Ctx NET_W32;
|
extern NET_W32_Ctx NET_W32;
|
||||||
@ -159,6 +169,7 @@ extern NET_W32_Ctx NET_W32;
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Helpers
|
//~ Helpers
|
||||||
|
|
||||||
|
NET_W32_DummySocket NET_W32_CreateDummySocket(void);
|
||||||
NET_W32_Pipe *NET_W32_PipeFromHandle(NET_PipeHandle pipe_handle);
|
NET_W32_Pipe *NET_W32_PipeFromHandle(NET_PipeHandle pipe_handle);
|
||||||
NET_Key NET_W32_KeyFromAddress(struct sockaddr_in6 addr);
|
NET_Key NET_W32_KeyFromAddress(struct sockaddr_in6 addr);
|
||||||
struct sockaddr_in6 NET_W32_AddressFromKey(NET_Key key);
|
struct sockaddr_in6 NET_W32_AddressFromKey(NET_Key key);
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
//~ Opaque types
|
//~ Opaque types
|
||||||
|
|
||||||
Struct(PLT_Watch);
|
Struct(PLT_Watch);
|
||||||
Struct(PLT_Sock);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ File system types
|
//~ File system types
|
||||||
@ -27,34 +26,6 @@ Struct(PLT_FileMap)
|
|||||||
b32 valid;
|
b32 valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Address types
|
|
||||||
|
|
||||||
Enum(PLT_AddressFamily)
|
|
||||||
{
|
|
||||||
PLT_AddressFamily_Ipv4,
|
|
||||||
PLT_AddressFamily_Ipv6
|
|
||||||
};
|
|
||||||
|
|
||||||
Struct(PLT_Address)
|
|
||||||
{
|
|
||||||
b32 valid;
|
|
||||||
PLT_AddressFamily family;
|
|
||||||
// NOTE: ipnb & portnb are stored in network byte order
|
|
||||||
u8 ipnb[16];
|
|
||||||
u16 portnb;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Sock types
|
|
||||||
|
|
||||||
Struct(PLT_SockReadResult)
|
|
||||||
{
|
|
||||||
b32 valid; // Since data.len = 0 can be valid
|
|
||||||
PLT_Address address;
|
|
||||||
String data;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Message box types
|
//~ Message box types
|
||||||
|
|
||||||
@ -102,23 +73,6 @@ PLT_FileMap PLT_OpenFileMap(PLT_File file);
|
|||||||
void PLT_CloseFileMap(PLT_FileMap map);
|
void PLT_CloseFileMap(PLT_FileMap map);
|
||||||
String PLT_GetFileMapData(PLT_FileMap map);
|
String PLT_GetFileMapData(PLT_FileMap map);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ @hookdecl Address helpers
|
|
||||||
|
|
||||||
PLT_Address PLT_AddressFromString(String str);
|
|
||||||
PLT_Address PLT_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr);
|
|
||||||
PLT_Address PLT_AddressFromPort(u16 port);
|
|
||||||
String PLT_StringFromAddress(Arena *arena, PLT_Address address);
|
|
||||||
b32 PLT_MatchAddress(PLT_Address a, PLT_Address b);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ @hookdecl Socket
|
|
||||||
|
|
||||||
PLT_Sock *PLT_AcquireSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size);
|
|
||||||
void PLT_ReleaseSock(PLT_Sock *sock);
|
|
||||||
PLT_SockReadResult PLT_ReadSock(Arena *arena, PLT_Sock *sock);
|
|
||||||
void PLT_WriteSock(PLT_Sock *sock, PLT_Address address, String data);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ @hookdecl Utils
|
//~ @hookdecl Utils
|
||||||
|
|
||||||
|
|||||||
@ -8,10 +8,6 @@ void PLT_Bootstrap(void)
|
|||||||
//- Init watches pool
|
//- Init watches pool
|
||||||
PLT_W32.watches_arena = AcquireArena(Gibi(64));
|
PLT_W32.watches_arena = AcquireArena(Gibi(64));
|
||||||
|
|
||||||
// Init winsock
|
|
||||||
WSAStartup(MAKEWORD(2, 2), &PLT_W32.wsa_data);
|
|
||||||
PLT_W32.socks_arena = AcquireArena(Gibi(64));
|
|
||||||
|
|
||||||
// Init timer
|
// Init timer
|
||||||
DispatchWave(Lit("Win32 timer sync"), 1, PLT_W32_SyncTimerForever, 0);
|
DispatchWave(Lit("Win32 timer sync"), 1, PLT_W32_SyncTimerForever, 0);
|
||||||
}
|
}
|
||||||
@ -62,92 +58,6 @@ String PLT_W32_StringFromWin32Path(Arena *arena, wchar_t *src)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Address
|
|
||||||
|
|
||||||
PLT_W32_Address PLT_W32_Win32AddressFromPlatformAddress(PLT_Address addr)
|
|
||||||
{
|
|
||||||
PLT_W32_Address result = Zi;
|
|
||||||
if (addr.family == PLT_AddressFamily_Ipv4)
|
|
||||||
{
|
|
||||||
result.family = AF_INET;
|
|
||||||
result.size = sizeof(struct sockaddr_in);
|
|
||||||
result.sin.sin_port = addr.portnb;
|
|
||||||
result.sin.sin_family = result.family;
|
|
||||||
CopyBytes(&result.sin.sin_addr, addr.ipnb, 4);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.family = AF_INET6;
|
|
||||||
result.sin6.sin6_port = addr.portnb;
|
|
||||||
result.sin6.sin6_family = result.family;
|
|
||||||
result.size = sizeof(struct sockaddr_in6);
|
|
||||||
CopyBytes(&result.sin6.sin6_addr.s6_addr, addr.ipnb, 16);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If supplied address has ip INADDR_ANY (0), convert ip to localhost
|
|
||||||
PLT_W32_Address PLT_W32_ConvertAnyaddrToLocalhost(PLT_W32_Address addr)
|
|
||||||
{
|
|
||||||
if (addr.family == AF_INET)
|
|
||||||
{
|
|
||||||
u8 *bytes = (u8 *)&addr.sin.sin_addr;
|
|
||||||
b32 is_any = 1;
|
|
||||||
for (u64 i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
if (bytes[i] != 0)
|
|
||||||
{
|
|
||||||
is_any = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (is_any)
|
|
||||||
{
|
|
||||||
bytes[0] = 127;
|
|
||||||
bytes[3] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (addr.family == AF_INET6)
|
|
||||||
{
|
|
||||||
u8 *bytes = (u8 *)&addr.sin.sin_addr;
|
|
||||||
b32 is_any = 1;
|
|
||||||
for (u64 i = 0; i < 16; ++i)
|
|
||||||
{
|
|
||||||
if (bytes[i] != 0)
|
|
||||||
{
|
|
||||||
is_any = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (is_any)
|
|
||||||
{
|
|
||||||
bytes[15] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
PLT_Address PLT_W32_PlatformAddressFromWin32Address(PLT_W32_Address ws_addr)
|
|
||||||
{
|
|
||||||
PLT_Address result = Zi;
|
|
||||||
if (ws_addr.family == AF_INET)
|
|
||||||
{
|
|
||||||
result.family = PLT_AddressFamily_Ipv4;
|
|
||||||
result.portnb = ws_addr.sin.sin_port;
|
|
||||||
CopyBytes(result.ipnb, &ws_addr.sin.sin_addr, 4);
|
|
||||||
result.valid = 1;
|
|
||||||
}
|
|
||||||
else if (ws_addr.family == AF_INET6)
|
|
||||||
{
|
|
||||||
result.family = PLT_AddressFamily_Ipv6;
|
|
||||||
result.portnb = ws_addr.sin6.sin6_port;
|
|
||||||
CopyBytes(result.ipnb, &ws_addr.sin6.sin6_addr.s6_addr, 16);
|
|
||||||
result.valid = 1;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Timer job
|
//~ Timer job
|
||||||
|
|
||||||
@ -503,317 +413,6 @@ String PLT_GetFileMapData(PLT_FileMap map)
|
|||||||
return map.mapped_memory;
|
return map.mapped_memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ @hookimpl Address helpers
|
|
||||||
|
|
||||||
PLT_Address PLT_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr)
|
|
||||||
{
|
|
||||||
PLT_Address result = Zi;
|
|
||||||
|
|
||||||
struct addrinfo hints = Zi;
|
|
||||||
hints.ai_family = AF_UNSPEC;
|
|
||||||
hints.ai_socktype = SOCK_DGRAM;
|
|
||||||
hints.ai_flags = AI_PASSIVE;
|
|
||||||
|
|
||||||
struct addrinfo *ai_result = 0;
|
|
||||||
i32 status = getaddrinfo(ip_cstr, port_cstr, &hints, &ai_result);
|
|
||||||
if (status == 0)
|
|
||||||
{
|
|
||||||
while (ai_result)
|
|
||||||
{
|
|
||||||
if (ai_result->ai_family == AF_INET)
|
|
||||||
{
|
|
||||||
struct sockaddr_in *sockaddr = (struct sockaddr_in *)ai_result->ai_addr;
|
|
||||||
result.valid = 1;
|
|
||||||
result.family = PLT_AddressFamily_Ipv4;
|
|
||||||
result.portnb = sockaddr->sin_port;
|
|
||||||
StaticAssert(sizeof(sockaddr->sin_addr) == 4);
|
|
||||||
CopyBytes(result.ipnb, (void *)&sockaddr->sin_addr, 4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (ai_result->ai_family == AF_INET6)
|
|
||||||
{
|
|
||||||
// TODO: Enable ipv6
|
|
||||||
// struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)ai_result->ai_addr;
|
|
||||||
// result.valid = 1;
|
|
||||||
// result.family = PLT_AddressFamily_Ipv6;
|
|
||||||
// result.portnb = sockaddr->sin6_port;
|
|
||||||
// StaticAssert(sizeof(sockaddr->sin6_addr) == 16);
|
|
||||||
// CopyBytes(result.ipnb, (void *)&sockaddr->sin6_addr, 16);
|
|
||||||
// break;
|
|
||||||
}
|
|
||||||
ai_result = ai_result->ai_next;
|
|
||||||
}
|
|
||||||
freeaddrinfo(ai_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
PLT_Address PLT_AddressFromString(String str)
|
|
||||||
{
|
|
||||||
// Parse string into ip & port
|
|
||||||
u8 ip_buff[1024];
|
|
||||||
u8 port_buff[countof(ip_buff)];
|
|
||||||
char *ip_cstr = 0;
|
|
||||||
char *port_cstr = 0;
|
|
||||||
{
|
|
||||||
u64 colon_count = 0;
|
|
||||||
for (u64 i = 0; i < str.len; ++i)
|
|
||||||
{
|
|
||||||
u8 c = str.text[i];
|
|
||||||
if (c == ':')
|
|
||||||
{
|
|
||||||
++colon_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
u64 ip_len = 0;
|
|
||||||
u64 port_len = 0;
|
|
||||||
u64 parse_len = MinU64(MinU64(str.len, countof(ip_buff) - 1), countof(port_buff) - 1);
|
|
||||||
if (colon_count > 1 && str.text[0] == '[')
|
|
||||||
{
|
|
||||||
// Parse ipv6 with port
|
|
||||||
b32 parse_addr = 1;
|
|
||||||
for (u64 i = 1; i < parse_len; ++i)
|
|
||||||
{
|
|
||||||
u8 c = str.text[i];
|
|
||||||
if (parse_addr)
|
|
||||||
{
|
|
||||||
if (c == ']')
|
|
||||||
{
|
|
||||||
parse_addr = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ip_buff[ip_len] = c;
|
|
||||||
++ip_len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (c != ':')
|
|
||||||
{
|
|
||||||
port_buff[port_len] = c;
|
|
||||||
++port_len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (colon_count == 1)
|
|
||||||
{
|
|
||||||
// Parse address with port
|
|
||||||
b32 parse_addr = 1;
|
|
||||||
for (u64 i = 0; i < parse_len; ++i)
|
|
||||||
{
|
|
||||||
u8 c = str.text[i];
|
|
||||||
if (parse_addr)
|
|
||||||
{
|
|
||||||
if (c == ':')
|
|
||||||
{
|
|
||||||
parse_addr = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ip_buff[ip_len] = c;
|
|
||||||
++ip_len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
port_buff[port_len] = c;
|
|
||||||
++port_len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Copy address without port
|
|
||||||
ip_len = MinU64(str.len, countof(ip_buff) - 1);
|
|
||||||
CopyBytes(ip_buff, str.text, ip_len);
|
|
||||||
}
|
|
||||||
if (ip_len > 0)
|
|
||||||
{
|
|
||||||
ip_buff[ip_len] = 0;
|
|
||||||
ip_cstr = (char *)ip_buff;
|
|
||||||
}
|
|
||||||
if (port_len > 0)
|
|
||||||
{
|
|
||||||
port_buff[port_len] = 0;
|
|
||||||
port_cstr = (char *)port_buff;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PLT_Address result = PLT_AddressFromIpPortCstr(ip_cstr, port_cstr);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
PLT_Address PLT_AddressFromPort(u16 port)
|
|
||||||
{
|
|
||||||
u8 port_buff[128];
|
|
||||||
char *port_cstr = 0;
|
|
||||||
{
|
|
||||||
u8 port_buff_reverse[countof(port_buff)];
|
|
||||||
u64 port_len = 0;
|
|
||||||
while (port > 0 && port_len < (countof(port_buff) - 1))
|
|
||||||
{
|
|
||||||
u8 digit = port % 10;
|
|
||||||
port /= 10;
|
|
||||||
port_buff_reverse[port_len] = '0' + digit;
|
|
||||||
++port_len;
|
|
||||||
}
|
|
||||||
for (u64 i = 0; i < port_len; ++i)
|
|
||||||
{
|
|
||||||
u64 j = port_len - 1 - i;
|
|
||||||
port_buff[i] = port_buff_reverse[j];
|
|
||||||
}
|
|
||||||
if (port_len > 0)
|
|
||||||
{
|
|
||||||
port_buff[port_len] = 0;
|
|
||||||
port_cstr = (char *)port_buff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PLT_Address result = PLT_AddressFromIpPortCstr(0, port_cstr);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
String PLT_StringFromAddress(Arena *arena, PLT_Address address)
|
|
||||||
{
|
|
||||||
String result = Zi;
|
|
||||||
|
|
||||||
if (address.family == PLT_AddressFamily_Ipv6)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u8 ip[4];
|
|
||||||
for (u32 i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
ip[i] = ntohs(address.ipnb[i]);
|
|
||||||
}
|
|
||||||
u16 port = ntohs(address.portnb);
|
|
||||||
result = StringF(arena, "%F.%F.%F.%F:%F", FmtUint(ip[0]), FmtUint(ip[1]), FmtUint(ip[2]), FmtUint(ip[3]), FmtUint(port));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
b32 PLT_MatchAddress(PLT_Address a, PLT_Address b)
|
|
||||||
{
|
|
||||||
return MatchStruct(&a, &b);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ @hookimpl Socket
|
|
||||||
|
|
||||||
PLT_Sock *PLT_AcquireSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size)
|
|
||||||
{
|
|
||||||
PLT_W32_Sock *ws = 0;
|
|
||||||
{
|
|
||||||
Lock lock = LockE(&PLT_W32.socks_mutex);
|
|
||||||
if (PLT_W32.first_free_sock)
|
|
||||||
{
|
|
||||||
ws = PLT_W32.first_free_sock;
|
|
||||||
PLT_W32.first_free_sock = ws->next_free;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ws = PushStructNoZero(PLT_W32.socks_arena, PLT_W32_Sock);
|
|
||||||
}
|
|
||||||
Unlock(&lock);
|
|
||||||
}
|
|
||||||
ZeroStruct(ws);
|
|
||||||
|
|
||||||
PLT_Address addr = PLT_AddressFromPort(listen_port);
|
|
||||||
PLT_W32_Address bind_address = PLT_W32_Win32AddressFromPlatformAddress(addr);
|
|
||||||
ws->sock = socket(bind_address.family, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
{
|
|
||||||
i32 sb = sndbuf_size;
|
|
||||||
i32 rb = rcvbuf_size;
|
|
||||||
u32 imode = 1;
|
|
||||||
setsockopt(ws->sock, SOL_SOCKET, SO_SNDBUF, (char *)&sb, sizeof(sb));
|
|
||||||
setsockopt(ws->sock, SOL_SOCKET, SO_RCVBUF, (char *)&rb, sizeof(rb));
|
|
||||||
ioctlsocket(ws->sock, FIONBIO, (unsigned long *)&imode);
|
|
||||||
}
|
|
||||||
bind(ws->sock, &bind_address.sa, bind_address.size);
|
|
||||||
|
|
||||||
return (PLT_Sock *)ws;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PLT_ReleaseSock(PLT_Sock *sock)
|
|
||||||
{
|
|
||||||
PLT_W32_Sock *ws = (PLT_W32_Sock *)sock;
|
|
||||||
closesocket(ws->sock);
|
|
||||||
Lock lock = LockE(&PLT_W32.socks_mutex);
|
|
||||||
{
|
|
||||||
ws->next_free = PLT_W32.first_free_sock;
|
|
||||||
PLT_W32.first_free_sock = ws;
|
|
||||||
}
|
|
||||||
Unlock(&lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
PLT_SockReadResult PLT_ReadSock(Arena *arena, PLT_Sock *sock)
|
|
||||||
{
|
|
||||||
PLT_W32_Sock *ws = (PLT_W32_Sock *)sock;
|
|
||||||
|
|
||||||
u64 read_buff_size = Kibi(64);
|
|
||||||
String read_buff = Zi;
|
|
||||||
read_buff.len = read_buff_size;
|
|
||||||
read_buff.text = PushStructsNoZero(arena, u8, read_buff_size);
|
|
||||||
|
|
||||||
PLT_SockReadResult result = Zi;
|
|
||||||
|
|
||||||
PLT_W32_Address ws_addr = Zi;
|
|
||||||
ws_addr.size = sizeof(ws_addr.sas);
|
|
||||||
|
|
||||||
i32 size = recvfrom(ws->sock, (char *)read_buff.text, read_buff.len, 0, &ws_addr.sa, &ws_addr.size);
|
|
||||||
ws_addr.family = ws_addr.sin.sin_family;
|
|
||||||
|
|
||||||
result.address = PLT_W32_PlatformAddressFromWin32Address(ws_addr);
|
|
||||||
if (size >= 0)
|
|
||||||
{
|
|
||||||
AddGstat(SockBytesReceived, size);
|
|
||||||
result.data.text = read_buff.text;
|
|
||||||
result.data.len = size;
|
|
||||||
result.valid = 1;
|
|
||||||
|
|
||||||
// PopStruct arena back to end of msg
|
|
||||||
PopTo(arena, arena->pos - read_buff_size + size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (IsRtcEnabled)
|
|
||||||
{
|
|
||||||
i32 err = WSAGetLastError();
|
|
||||||
if (err != WSAEWOULDBLOCK && err != WSAETIMEDOUT && err != WSAECONNRESET)
|
|
||||||
{
|
|
||||||
Assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PLT_WriteSock(PLT_Sock *sock, PLT_Address address, String data)
|
|
||||||
{
|
|
||||||
PLT_W32_Sock *ws = (PLT_W32_Sock *)sock;
|
|
||||||
PLT_W32_Address ws_addr = PLT_W32_Win32AddressFromPlatformAddress(address);
|
|
||||||
i32 size = sendto(ws->sock, (char *)data.text, data.len, 0, &ws_addr.sa, ws_addr.size);
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
AddGstat(SockBytesSent, size);
|
|
||||||
}
|
|
||||||
if (IsRtcEnabled)
|
|
||||||
{
|
|
||||||
if (size != (i32)data.len)
|
|
||||||
{
|
|
||||||
i32 err = WSAGetLastError();
|
|
||||||
Assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ @hookimpl Utils
|
//~ @hookimpl Utils
|
||||||
|
|
||||||
|
|||||||
@ -9,31 +9,6 @@ Struct(PLT_W32_Watch)
|
|||||||
u8 results_buff[Kibi(64)];
|
u8 results_buff[Kibi(64)];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Address types
|
|
||||||
|
|
||||||
Struct(PLT_W32_Address)
|
|
||||||
{
|
|
||||||
i32 size;
|
|
||||||
i32 family;
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct sockaddr_storage sas;
|
|
||||||
struct sockaddr sa;
|
|
||||||
struct sockaddr_in sin;
|
|
||||||
struct sockaddr_in6 sin6;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Sock types
|
|
||||||
|
|
||||||
Struct(PLT_W32_Sock)
|
|
||||||
{
|
|
||||||
SOCKET sock;
|
|
||||||
PLT_W32_Sock *next_free;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ State types
|
//~ State types
|
||||||
|
|
||||||
@ -47,12 +22,6 @@ Struct(PLT_W32_Ctx)
|
|||||||
Arena *watches_arena;
|
Arena *watches_arena;
|
||||||
PLT_W32_Watch *watches_first_free;
|
PLT_W32_Watch *watches_first_free;
|
||||||
|
|
||||||
//- Socket pool
|
|
||||||
WSADATA wsa_data;
|
|
||||||
Arena *socks_arena;
|
|
||||||
Mutex socks_mutex;
|
|
||||||
PLT_W32_Sock *first_free_sock;
|
|
||||||
|
|
||||||
//- Timer
|
//- Timer
|
||||||
Fence timer_fence;
|
Fence timer_fence;
|
||||||
Atomic64Padded average_timer_period_ns;
|
Atomic64Padded average_timer_period_ns;
|
||||||
@ -70,13 +39,6 @@ DateTime PLT_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st);
|
|||||||
|
|
||||||
String PLT_W32_StringFromWin32Path(Arena *arena, wchar_t *src);
|
String PLT_W32_StringFromWin32Path(Arena *arena, wchar_t *src);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//~ Address
|
|
||||||
|
|
||||||
PLT_W32_Address PLT_W32_Win32AddressFromPlatformAddress(PLT_Address addr);
|
|
||||||
PLT_W32_Address PLT_W32_ConvertAnyaddrToLocalhost(PLT_W32_Address addr);
|
|
||||||
PLT_Address PLT_W32_PlatformAddressFromWin32Address(PLT_W32_Address ws_addr);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Timer job
|
//~ Timer job
|
||||||
|
|
||||||
|
|||||||
@ -3759,7 +3759,11 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
// FIXME: Remove this (testing)
|
// FIXME: Remove this (testing)
|
||||||
|
|
||||||
NET_Key server_key = NET_KeyFromString(Lit("127.0.0.1"), Lit("22121"));
|
NET_Key server_key = NET_KeyFromString(Lit("127.0.0.1"), Lit("22121"));
|
||||||
NET_Push(net_pipe, server_key, Lit("HELLO!!!!"), 0);
|
|
||||||
|
if (frame->held_buttons[Button_R])
|
||||||
|
{
|
||||||
|
NET_Push(net_pipe, server_key, Lit("HELLO!!!!"), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user