Lumenarium/src/app/platform_win32/win32_foldhaus_socket.h

140 lines
3.7 KiB
C

//
// File: win32_foldhaus_socket.h
// Author: Peter Slattery
// Creation Date: 2020-10-03
//
#ifndef WIN32_FOLDHAUS_SOCKET_H
struct win32_socket
{
SOCKET Socket;
};
struct win32_socket_array
{
win32_socket* Values;
s32 CountMax;
s32 Count;
};
//////////////////////
//
// Win32 Socket Array
internal win32_socket_array
Win32SocketArray_Create(u32 CountMax, gs_memory_arena* Storage)
{
win32_socket_array Result = {};
Result.CountMax = CountMax;
Result.Values = PushArray(Storage, win32_socket, CountMax);
return Result;
}
internal s32
Win32SocketArray_Take(win32_socket_array* Array)
{
Assert(Array->Count < Array->CountMax);
s32 Result = Array->Count++;
win32_socket* Socket = Array->Values + Result;
*Socket = {0};
return Result;
}
internal win32_socket*
Win32SocketArray_Get(win32_socket_array Array, s32 Index)
{
Assert(Index < Array.Count);
win32_socket* Result = Array.Values + Index;
return Result;
}
//////////////////////
//
// Win32 Socket System
global win32_socket_array Win32Sockets;
internal s32
Win32Socket_SetOption(win32_socket* Socket, s32 Level, s32 Option, const char* OptionValue, s32 OptionLength)
{
int Error = setsockopt(Socket->Socket, Level, Option, OptionValue, OptionLength);
if (Error == SOCKET_ERROR)
{
Error = WSAGetLastError();
// TODO(Peter): :ErrorLogging
}
return Error;
}
internal s32
Win32Socket_SetOption(platform_socket_handle SocketHandle, s32 Level, s32 Option, const char* OptionValue, s32 OptionLength)
{
win32_socket* Socket = Win32SocketArray_Get(Win32Sockets, (s32)SocketHandle);
return Win32Socket_SetOption(Socket, Level, Option, OptionValue, OptionLength);
}
PLATFORM_GET_SOCKET_HANDLE(Win32GetSocketHandle)
{
// NOTE(Peter): These used to be passed in as paramters, but we only use this function
// with AF_INET, SOCK_DGRAM, and Protocol = 0. These are also platform specific values
// so I was having to include windows.h in the platform agnostic code to accomodate that
// function signature.
s32 AddressFamily = AF_INET;
s32 Type = SOCK_DGRAM;
s32 Protocol = 0;
s32 Result = Win32SocketArray_Take(&Win32Sockets);
win32_socket* Socket = Win32SocketArray_Get(Win32Sockets, Result);
Socket->Socket = socket(AddressFamily, Type, Protocol);
if (Socket->Socket != INVALID_SOCKET)
{
int Error = Win32Socket_SetOption(Socket, IPPROTO_IP, IP_MULTICAST_TTL,
(const char*)(&Multicast_TimeToLive), sizeof(Multicast_TimeToLive));
}
else
{
s32 Error = WSAGetLastError();
InvalidCodePath;
}
return (platform_socket_handle)Result;
}
internal s32
Win32Socket_SendTo(platform_socket_handle SocketHandle, u32 Address, u32 Port, const char* Buffer, s32 BufferLength, s32 Flags)
{
win32_socket* Socket = Win32SocketArray_Get(Win32Sockets, (s32)SocketHandle);
sockaddr_in SockAddress = {};
SockAddress.sin_family = AF_INET;
SockAddress.sin_port = HostToNetU16(Port);
SockAddress.sin_addr.s_addr = HostToNetU32(Address);
s32 LengthSent = sendto(Socket->Socket, Buffer, BufferLength, Flags, (sockaddr*)&SockAddress, sizeof(sockaddr_in));
if (LengthSent == SOCKET_ERROR)
{
s32 Error = WSAGetLastError();
if (Error == 10051)
{
}
else
{
// TODO(Peter): :ErrorLogging
InvalidCodePath;
}
}
return LengthSent;
}
internal void
Win32Socket_Close(win32_socket* Socket)
{
closesocket(Socket->Socket);
Socket->Socket = INVALID_SOCKET;
}
#define WIN32_FOLDHAUS_SOCKET_H
#endif // WIN32_FOLDHAUS_SOCKET_H