package sdl2_net import "core:c" import SDL ".." when ODIN_OS == .Windows { foreign import lib "SDL2_net.lib" } else { foreign import lib "system:SDL2_net" } bool :: SDL.bool MAJOR_VERSION :: 2 MINOR_VERSION :: 0 PATCHLEVEL :: 1 IPaddress :: struct { host: u32, /* 32-bit IPv4 host address */ port: u16, /* 16-bit protocol port */ } INADDR_ANY :: 0x00000000 INADDR_NONE :: 0xFFFFFFFF INADDR_LOOPBACK :: 0x7f000001 INADDR_BROADCAST :: 0xFFFFFFFF @(default_calling_convention="c", link_prefix="SDLNet_") foreign lib { Linked_Version :: proc() -> ^SDL.version --- Init :: proc() -> c.int --- Quit :: proc() --- ResolveHost :: proc(address: ^IPaddress, host: cstring, port: u16) -> c.int --- ResolveIP :: proc(ip: ^IPaddress) -> cstring --- GetLocalAddresses :: proc(addresses: ^IPaddress, maxcount: c.int) -> c.int --- } /***********************************************************************/ /* TCP network API */ /***********************************************************************/ TCPsocket :: distinct rawptr @(default_calling_convention="c", link_prefix="SDLNet_") foreign lib { TCP_Open :: proc(ip: ^IPaddress) -> TCPsocket --- TCP_Accept :: proc(server: TCPsocket) -> TCPsocket --- TCP_GetPeerAddress :: proc(sock: TCPsocket) -> ^IPaddress --- TCP_Send :: proc(sock: TCPsocket, data: rawptr, len: c.int) -> c.int --- TCP_Recv :: proc(sock: TCPsocket, data: rawptr, maxlen: c.int) -> c.int --- TCP_Close :: proc(sock: TCPsocket) --- } /* The maximum channels on a a UDP socket */ MAX_UDPCHANNELS :: 32 /* The maximum addresses bound to a single UDP socket channel */ MAX_UDPADDRESSES :: 4 UDPsocket :: distinct rawptr UDPpacket :: struct { channel: c.int, /* The src/dst channel of the packet */ data: [^]u8, /* The packet data */ len: c.int, /* The length of the packet data */ maxlen: c.int, /* The size of the data buffer */ status: c.int, /* packet status after sending */ address: IPaddress, /* The source/dest address of an incoming/outgoing packet */ } /***********************************************************************/ /* UDP network API */ /***********************************************************************/ @(default_calling_convention="c", link_prefix="SDLNet_") foreign lib { AllocPacket :: proc(size: c.int) -> ^UDPpacket --- ResizePacket :: proc(packet: ^UDPpacket, newsize: c.int) -> c.int --- FreePacket :: proc(packet: ^UDPpacket) --- AllocPacketV :: proc(howmany: c.int, size: c.int) -> [^]^UDPpacket --- FreePacketV :: proc(packetV: [^]^UDPpacket) --- UDP_Open :: proc(port: u16) -> UDPsocket --- UDP_SetPacketLoss :: proc(sock: UDPsocket, percent: c.int) --- UDP_Bind :: proc(sock: UDPsocket, channel: c.int, address: ^IPaddress) -> c.int --- UDP_Unbind :: proc(sock: UDPsocket, channel: c.int) --- UDP_GetPeerAddress :: proc(sock: UDPsocket, channel: c.int) -> IPaddress --- UDP_SendV :: proc(sock: UDPsocket, packets: [^]^UDPpacket, npackets: c.int) -> c.int --- UDP_Send :: proc(sock: UDPsocket, channel: c.int, packet: ^UDPpacket) -> c.int --- UDP_RecvV :: proc(sock: UDPsocket, packets: [^]^UDPpacket) -> c.int --- UDP_Recv :: proc(sock: UDPsocket, packet: ^UDPpacket) -> c.int --- UDP_Close :: proc(sock: UDPsocket) --- } AllocPacketSlice :: proc "c" (howmany: c.int, size: c.int) -> []^UDPpacket { if packets := AllocPacketV(howmany, size); packets != nil { return packets[:howmany] } return nil } FreePacketSlice :: proc "c" (packets: []^UDPpacket) { FreePacketV(raw_data(packets)) } UDP_SendSlice :: proc "c" (sock: UDPsocket, packets: []^UDPpacket) -> c.int { return UDP_SendV(sock, raw_data(packets), c.int(len(packets))) } /***********************************************************************/ /* Hooks for checking sockets for available data */ /***********************************************************************/ SocketSet :: distinct rawptr /* Any network socket can be safely cast to this socket type */ GenericSocket :: ^struct { ready: c.int } TCP_AddSocket :: #force_inline proc "c" (set: SocketSet, sock: TCPsocket) -> c.int { return AddSocket(set, (GenericSocket)(sock)) } UDP_AddSocket :: #force_inline proc "c" (set: SocketSet, sock: UDPsocket) -> c.int { return AddSocket(set, (GenericSocket)(sock)) } TCP_DelSocket :: #force_inline proc "c" (set: SocketSet, sock: TCPsocket) -> c.int { return DelSocket(set, (GenericSocket)(sock)) } UDP_DelSocket :: #force_inline proc "c" (set: SocketSet, sock: UDPsocket) -> c.int { return DelSocket(set, (GenericSocket)(sock)) } SocketReady :: #force_inline proc "c" (sock: rawptr) -> bool { s := (GenericSocket)(sock) return bool(s != nil && s.ready != 0) } @(default_calling_convention="c", link_prefix="SDLNet_") foreign lib { AllocSocketSet :: proc(maxsockets: c.int) -> SocketSet --- AddSocket :: proc(set: SocketSet, sock: GenericSocket) -> c.int --- DelSocket :: proc(set: SocketSet, sock: GenericSocket) -> c.int --- CheckSockets :: proc(set: SocketSet, timeout: u32) -> c.int --- FreeSocketSet :: proc(set: SocketSet) --- } /***********************************************************************/ /* Error reporting functions */ /***********************************************************************/ @(default_calling_convention="c", link_prefix="SDLNet_") foreign lib { SetError :: proc(fmt: cstring, #c_vararg args: ..any) --- GetError :: proc() -> cstring --- } /***********************************************************************/ /* Inline functions to read/write network data */ /***********************************************************************/ /* Write a 16/32-bit value to network packet buffer */ Write16 :: #force_inline proc "c" (value: u16, areap: rawptr) { area := (^[2]u8)(areap) area[0] = u8((value >> 8) & 0xFF) area[1] = u8( value & 0xFF) } Write32 :: #force_inline proc "c" (value: u32, areap: rawptr) { area := (^[4]u8)(areap) area[0] = u8((value >> 24) & 0xFF) area[1] = u8((value >> 16) & 0xFF) area[2] = u8((value >> 8) & 0xFF) area[3] = u8( value & 0xFF) } /* Read a 16/32-bit value from network packet buffer */ Read16 :: #force_inline proc "c" (areap: rawptr) -> u16 { area := (^[2]u8)(areap) return u16(area[0])<<8 | u16(area[1]) } Read32 :: #force_inline proc "c" (areap: rawptr) -> u32 { area := (^[4]u8)(areap) return u32(area[0])<<24 | u32(area[1])<<16 | u32(area[2])<<8 | u32(area[3]) }