# New API: Comments?

**URL:** <https://discourse.libsdl.org/t/new-api-comments/651>\
**Category:** SDL Development\
**Created:** [October 29, 1998, 8:39pm UTC](https://discourse.libsdl.org/t/new-api-comments/651 "1998-10-29T20:39:16Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [October 29, 1998, 8:39pm UTC](https://discourse.libsdl.org/t/new-api-comments/651/1 "1998-10-29T20:39:16Z")

</div>

1. You’re still not object-oriented. You therefore still can’t use this  
api more  
than once in a single process. Please consider defining a type  
sdlnet\_t  
and making all the calls that currently need static data store it in  
the sdlnet\_t instead, and take a pointer to an sdlnet\_t!

IMHO, the function that picks the UDP port number ought to be  
called something like sdlnet\_udp\_init(sdlnet\_t \*, short port), to indicate  
you do it only once per session.

I’m very confused about what a channel is and what a socket is.  
In my API, the send and receive routines operate on handles,  
which are integers in the range 0…nhandles.

Your channel seems to be a subaddress on a socket? I think that rather  
than having calls that take a subchannel like that,

1. Types need to start with the standard prefix, too. All identifiers that  
get  
declared in your .h file must be protected in this way from clashes.  
e.g. sdlnet\_ipadr\_t rather than IPAddress.

My taste also runs towards the left-to-right more-generic-to-less-generic,  
e.g. sdlnet\_udp\_sendv().

1. sendudp should not do a soft broadcast; let the higher level do that.  
It should do a hardware broadcast. This is partly because hardware  
broadcasts are needed on LAN’s to advertize games, and partly  
because the upper layer usually has handles open to extra hosts  
not involved in the game per se (e.g. an auxillary server, or a lurker).  
Well, at least _my_ upper layer does 🙂

2. The packet buffer should have a status field so that each packet  
processed by send or receive can have a separate result code, IMHO.  
Your doc should mention that the API is designed to reuse existing  
packet buffers rather than constantly allocate new ones, to avoid  
heap fragmentation.

3. getpeername probably needs to return all bound addresses for that peer.  
Likewise, setpeername should set all bound addresses.  
One address, the first one in the vector, should by convention be  
the primary address - the one visible to the outside world. Addresses  
should be six bytes long, because the port number is variable under NAT.

Uh, I’m not sure about passing a channel number to the bind function.  
I’d rather call that sdlnet\_udp\_open(), and pass it a vector of addresses.  
Most users will pass only one address.

1. Tactically speaking, it is a very good idea to have a separate .h file  
for the shared error code type and #define’s for a family of modules,  
e.g. sdlerr.h. That way, you can pull in the error codes into lowlevel  
modules  
like sdlnet without pulling in higher-level baggage.\> -----Original Message-----

> From: Sam Lantinga [SMTP:slouken at [devolution.com](http://devolution.com)]  
> Sent: Thursday, October 29, 1998 12:12 PM  
> To: @Kegel_Dan  
> Subject: New API: Comments?
> 
> Note that I omitted getpeername() on purpose.  
> I’m still working out the best implementation.
> 
> /\*  
> NETLIB: An example cross-platform network library for use with SDL  
> Copyright (C) 1997 Sam Lantinga
> 
> ```
> This program is free software; you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
> 
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU General Public License for more details.
> 
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
> 
> ```
> 
> USA
> 
> ```
> Sam Lantinga
> 5635-34 Springhouse Dr.
> Pleasanton, CA 94588 (USA)
> slouken at devolution.com
> 
> ```
> 
> \*/
> 
> #ifndef \_SDLnet\_h  
> #define \_SDLnet\_h
> 
> #include “SDL.h”
> 
> /\* Set up for C function definitions, even when using C++ \*/  
> #ifdef \_\_cplusplus  
> extern “C” {  
> #endif
> 
> /\* Initialize/Cleanup the network API  
> SDL must be initialized before calls to functions in this library,  
> because this library uses utility functions from the SDL library.  
> \*/  
> extern int Net\_Init(void);  
> extern void Net\_Quit(void);
> 
> /_**/  
> /\* TCP network API \*/  
> /**_/
> 
> typedef struct TCPsocket \*TCPsocket;
> 
> /\* Open a TCP network socket  
> If ‘remote’ is NULL, this creates a local server socket on the given  
> port,  
> otherwise a TCP connection to the remote host and port is attempted.  
> The newly created socket is returned, or NULL if there was an error.  
> \*/  
> extern TCPsocket SDLNet\_OpenTCP(char \*remote, Uint16 port);
> 
> /\* Accept an incoming connection on the given server socket.  
> The newly created socket is returned, or NULL if there was an error.  
> \*/  
> extern TCPsocket SDLNet\_AcceptTCP(TCPsocket server);
> 
> /\* Send ‘len’ bytes of ‘data’ over the non-server socket ‘sock’  
> This function returns the actual amount of data sent. If the return  
> value  
> is less than the amount of data sent, then either the remote connection  
> was  
> closed, or an unknown socket error occurred.  
> \*/  
> extern int SDLNet\_SendTCP(TCPsocket sock, char \*data, int len);
> 
> /\* Returns true if the socket is ready to recieve data, blocking for up to  
> ‘timeout’ milliseconds before returning.  
> If a server socket is passed to this function, then it will return true  
> when there is an incoming connection to be accepted.  
> \*/  
> extern int SDLNet\_ReadyTCP(UDPsocket sock, Uint32 timeout);
> 
> /\* Receive up to ‘maxlen’ bytes of data over the non-server socket ‘sock’,  
> and store them in the buffer pointed to by ‘data’.  
> This function returns the actual amount of data received. If the  
> return  
> value is less than or equal to zero, then either the remote connection  
> was  
> closed, or an unknown socket error occurred.  
> \*/  
> extern int SDLNet\_RecvTCP(TCPsocket sock, char \*data, int maxlen);
> 
> /\* Close a TCP network socket \*/  
> extern void SDLNet\_CloseTCP(TCPsocket sock);
> 
> /_**/  
> /\* UDP network API \*/  
> /**_/
> 
> /\* The maximum channels on a a UDP socket (should be a multiple of 8) _/  
> #define SDLNET\_MAX\_UDPCHANNELS 32  
> /_ The maximum addresses bound to a single UDP socket channel \*/  
> #define SDLNET\_MAX\_UDPADDRESSES 4
> 
> typedef struct UDPsocket \*UDPsocket;  
> typedef struct {  
> char _data; /_ The packet data _/  
> int len; /_ The length of the packet data _/  
> int maxlen; /_ The size of the data buffer _/  
> IPaddress src; /_ The source address of the packet _/  
> int channel; /_ The source channel of the packet \*/  
> } UDPpacket;
> 
> /\* Open a UDP network socket  
> If ‘port’ is non-zero, the UDP socket is bound to a local port.  
> This allows other systems to send to this socket  
> \*/  
> extern UDPsocket SDLNet\_OpenUDP(Uint16 port);
> 
> /\* Bind the address ‘address’ to the requested channel on the UDP socket.  
> If the channel is already bound, this new address will be added to the  
> valid addresses for the channel.  
> If the channel is -1, then the first unbound channel will be bound with  
> the given address.  
> This function returns the channel which was bound, or -1 on error.  
> \*/  
> extern int SDLNet\_BindUDP(UDPsocket sock, int channel, IPaddress address);
> 
> /\* Allocate/free a single UDP packet ‘size’ bytes long.  
> The new packet is returned, or NULL if the function ran out of memory.  
> \*/  
> extern UDPpacket \*SDLNet\_AllocPacket(int size);  
> extern void SDLNet\_FreePacket(UDPpacket \*packet);
> 
> /\* Allocate/Free a UDP packet vector (array of packets) of ‘howmany’  
> packets,  
> each ‘size’ bytes long.  
> A pointer to the first packet in the array is returned, or NULL if the  
> function ran out of memory.  
> \*/  
> extern UDPpacket \*\*SDLNet\_AllocPacketV(int howmany, int size);  
> extern void SDLNet\_FreePacketV(UDPpacket \*\*packetV);
> 
> /\* Send a vector of packets to the addresses bound to the given channel.  
> If ‘channel’ is -1, the packets are broadcast to every address on every  
> channel bound on the UDP socket.  
> This function returns the number of packets sent, or -1 on error.  
> \*/  
> extern int SDLNet\_SendVUDP(UDPsocket sock, int channel, int howmany,  
> UDPpacket \*\*packetV);  
> #define SDLNet\_SendUDP(s, c, p) SDLNet\_SendVUDP(s, c, 1, &p)
> 
> /\* Returns true if the socket is ready to recieve data, blocking for up to  
> ‘timeout’ milliseconds before returning.  
> \*/  
> extern int SDLNet\_ReadyUDP(UDPsocket sock, Uint32 timeout);
> 
> /\* Receive a vector of pending packets from the UDP socket.  
> The returned packets contain the source address and the channel they  
> arrived  
> on. If they did not arrive on a bound channel, the the channel will be  
> set  
> to -1.  
> This function returns the number of packets read from the network, or  
> -1  
> on error.  
> This function does not block, so can return 0 packets pending.  
> \*/  
> extern int SDLNet\_RecvVUDP(UDPsocket sock, int howmany, UDPpacket  
> \*\*packetV);  
> #define SDLNet\_RecvUDP(s, p) SDLNet\_SendVUDP(s, 1, &p)
> 
> /\* Close a UDP network socket \*/  
> extern void SDLNet\_CloseUDP(UDPsocket sock);
> 
> /_**/  
> /\* Platform-independent data conversion functions \*/  
> /**_/
> 
> /\* Write a 16/32 bit value to network packet buffer \*/  
> extern void Net\_Write16(Uint16 value, Uint8 \*area);  
> extern void Net\_Write32(Uint32 value, Uint8 \*area);
> 
> /\* Read a 16/32 bit value from network packet buffer \*/  
> extern Uint16 Net\_Read16(Uint8 \*area);  
> extern Uint32 Net\_Read32(Uint8 \*area);
> 
> /_**/  
> /\* Error reporting functions \*/  
> /**_/
> 
> /\* We’ll use SDL’s functions for error reporting \*/  
> #define Net\_SetError SDL\_SetError  
> #define Net\_GetError SDL\_GetError
> 
> /\* Ends C function definitions when using C++ _/  
> #ifdef \_\_cplusplus  
> };  
> #endif  
> #endif /_ \_SDLnet\_h \*/

---

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [October 29, 1998, 9:51pm UTC](https://discourse.libsdl.org/t/new-api-comments/651/2 "1998-10-29T21:51:17Z")

</div>

Last comments today. I gotta work, y’know!

> I am object oriented. The object is the TCPsocket or UDPsocket.  
> Ignore SDLNet\_Init(), and SDLNet\_Quit() – they are just used to initialize  
> the Win32 socket layer. A simple reference count in there will take care  
> of  
> multiple calls.  
> I am not using C++.  
> I see now that you’re doing what I was talking about. I was thrown off a  
> bit  
> by SDLNet\_UDPsocket. I still feel a little queasy. Fear not, it should  
> pass.

> > extern int SDLNet\_SendVUDP(UDPsocket sock, int channel, int howmany,  
> > UDPpacket \*\*packetV);  
> > Aha. You need to accept a vector of channel numbers here, too, to support  
> > groups and broadcast. So perhaps  
> > sdlnet\_udp\_send(sdlnet\_udp\_t \*sock, int \*channels, int nchannels,  
> > sdlnet\_packet\_t \*packetV, int npackets);

> 🙂 What are hardware broadcasts? 192.168.0.255?  
> Can you specify a port on a hardware broadcast?  
> Hardware broadcasts are when you send to address 255.255.255.255.  
> By the way, you might want to preopen a handle to that address.

Good question about the port. The only time you need hardware  
broadcast is when running on a LAN. In that case, everyone has to  
use the same port number. The hardware broadcast is sent and  
received with the same port number.  
When running on the Internet, the port number may vary for  
several reasons, but one doesn’t need hardware broadcast on the Internet.

> > 1. The packet buffer should have a status field so that each packet  
> > processed by send or receive can have a separate result code, IMHO.  
> > Did you catch this one ?-)

> udp\_socket = opensocket  
> for host in clients  
> do # bind the host address to the next free channel  
> sdlnet\_udp\_bind(udp\_socket, -1, host, port)  
> done

Small note: can’t assume you know all the IP adrs of the peers at this  
point. You’re more likely to do the binding when you receive a  
“please let me join” packet from an unbound source. Maybe sdlnet\_udp\_bind  
should take an IPAddress instead of separate host and port?

> ```
> # Receive status updates
> while numupdated < numclients
> do sdlnet_udp_recv(udp_socket, packets)
> for packet in packets
> do update(packet->channel, packet);
> ++numupdated
> done
> 
> ```

But what about dropped packets? In action sim land, one accepts that and  
moves  
on. (Strategy games in lockstep require a higher level protocol to make  
things  
reliable.) So a slightly better example is to just process all outstanding  
packets  
and move on. You still need an outer loop, in case your packet vector  
isn’t big enough.  
# Receive status updates until no more available  
while sdlnet\_udp\_recv(udp\_socket, packets, maxpackets) ==  
maxpackets  
do  
for packet in packets  
do  
…

> There is, SDL\_error.h  
> It’s just included in SDL.h  
> Am I misunderstanding you?  
> Yeah. You may find it painful to include SDL.h from within  
> submodules of SDL. Each .h file is protected against  
> multiple inclusion, but there are occasionally painful side  
> effects of including toplevel .h files in submodules.  
> It’s kind of like how your head hurts when you run into  
> those twisty passages all alike in Adventure 🙂  
> You’ll understand if/when you run into it, but for now,  
> I’m just suggesting that it’s good to include the weakest  
> .h files you possibly can inside submodule .h files.\> \> \> -----Original Message-----
> 
> > > From: Sam Lantinga [SMTP:slouken at [devolution.com](http://devolution.com)]  
> > > Sent: Thursday, October 29, 1998 12:12 PM  
> > > To: @Kegel_Dan  
> > > Subject: New API: Comments?
> > > 
> > > Note that I omitted getpeername() on purpose.  
> > > I’m still working out the best implementation.
> > > 
> > > /\*  
> > > NETLIB: An example cross-platform network library for use with  
> > > SDL  
> > > Copyright (C) 1997 Sam Lantinga
> > > 
> > > ```
> > > This program is free software; you can redistribute it and/or
> > > 
> > > ```
> 
> modify
> 
> > > ```
> > > it under the terms of the GNU General Public License as published
> > > 
> > > ```
> 
> by
> 
> > > ```
> > > the Free Software Foundation; either version 2 of the License, or
> > > (at your option) any later version.
> > > 
> > > This program is distributed in the hope that it will be useful,
> > > but WITHOUT ANY WARRANTY; without even the implied warranty of
> > > MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > > GNU General Public License for more details.
> > > 
> > > You should have received a copy of the GNU General Public License
> > > along with this program; if not, write to the Free Software
> > > Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> > > 
> > > ```
> 
> 02111-1307
> 
> > > USA
> > > 
> > > ```
> > > Sam Lantinga
> > > 5635-34 Springhouse Dr.
> > > Pleasanton, CA 94588 (USA)
> > > slouken at devolution.com
> > > 
> > > ```
> > > 
> > > \*/
> > > 
> > > #ifndef \_SDLnet\_h  
> > > #define \_SDLnet\_h
> > > 
> > > #include “SDL.h”
> > > 
> > > /\* Set up for C function definitions, even when using C++ \*/  
> > > #ifdef \_\_cplusplus  
> > > extern “C” {  
> > > #endif
> > > 
> > > /\* Initialize/Cleanup the network API  
> > > SDL must be initialized before calls to functions in this library,  
> > > because this library uses utility functions from the SDL library.  
> > > \*/  
> > > extern int Net\_Init(void);  
> > > extern void Net\_Quit(void);
> 
> /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
> 
> > > /\* TCP network API  
> > > \*/
> 
> /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
> 
> > > typedef struct TCPsocket \*TCPsocket;
> > > 
> > > /\* Open a TCP network socket  
> > > If ‘remote’ is NULL, this creates a local server socket on the  
> > > given  
> > > port,  
> > > otherwise a TCP connection to the remote host and port is  
> > > attempted.  
> > > The newly created socket is returned, or NULL if there was an  
> > > error.  
> > > \*/  
> > > extern TCPsocket SDLNet\_OpenTCP(char \*remote, Uint16 port);
> > > 
> > > /\* Accept an incoming connection on the given server socket.  
> > > The newly created socket is returned, or NULL if there was an  
> > > error.  
> > > \*/  
> > > extern TCPsocket SDLNet\_AcceptTCP(TCPsocket server);
> > > 
> > > /\* Send ‘len’ bytes of ‘data’ over the non-server socket ‘sock’  
> > > This function returns the actual amount of data sent. If the  
> > > return  
> > > value  
> > > is less than the amount of data sent, then either the remote  
> > > connection  
> > > was  
> > > closed, or an unknown socket error occurred.  
> > > \*/  
> > > extern int SDLNet\_SendTCP(TCPsocket sock, char \*data, int len);
> > > 
> > > /\* Returns true if the socket is ready to recieve data, blocking for  
> > > up to  
> > > ‘timeout’ milliseconds before returning.  
> > > If a server socket is passed to this function, then it will return  
> > > true  
> > > when there is an incoming connection to be accepted.  
> > > \*/  
> > > extern int SDLNet\_ReadyTCP(UDPsocket sock, Uint32 timeout);
> > > 
> > > /\* Receive up to ‘maxlen’ bytes of data over the non-server socket  
> > > ‘sock’,  
> > > and store them in the buffer pointed to by ‘data’.  
> > > This function returns the actual amount of data received. If the  
> > > return  
> > > value is less than or equal to zero, then either the remote  
> > > connection  
> > > was  
> > > closed, or an unknown socket error occurred.  
> > > \*/  
> > > extern int SDLNet\_RecvTCP(TCPsocket sock, char \*data, int maxlen);
> > > 
> > > /\* Close a TCP network socket \*/  
> > > extern void SDLNet\_CloseTCP(TCPsocket sock);
> 
> /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
> 
> > > /\* UDP network API  
> > > \*/
> 
> /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
> 
> > > /\* The maximum channels on a a UDP socket (should be a multiple of 8)  
> > > _/  
> > > #define SDLNET\_MAX\_UDPCHANNELS 32  
> > > /_ The maximum addresses bound to a single UDP socket channel \*/  
> > > #define SDLNET\_MAX\_UDPADDRESSES 4
> > > 
> > > typedef struct UDPsocket \*UDPsocket;  
> > > typedef struct {  
> > > char _data; /_ The packet data _/  
> > > int len; /_ The length of the packet data _/  
> > > int maxlen; /_ The size of the data buffer _/  
> > > IPaddress src; /_ The source address of the packet _/  
> > > int channel; /_ The source channel of the packet \*/  
> > > } UDPpacket;
> > > 
> > > /\* Open a UDP network socket  
> > > If ‘port’ is non-zero, the UDP socket is bound to a local port.  
> > > This allows other systems to send to this socket  
> > > \*/  
> > > extern UDPsocket SDLNet\_OpenUDP(Uint16 port);
> > > 
> > > /\* Bind the address ‘address’ to the requested channel on the UDP  
> > > socket.  
> > > If the channel is already bound, this new address will be added to  
> > > the  
> > > valid addresses for the channel.  
> > > If the channel is -1, then the first unbound channel will be bound  
> > > with  
> > > the given address.  
> > > This function returns the channel which was bound, or -1 on error.  
> > > \*/  
> > > extern int SDLNet\_BindUDP(UDPsocket sock, int channel, IPaddress  
> > > address);
> > > 
> > > /\* Allocate/free a single UDP packet ‘size’ bytes long.  
> > > The new packet is returned, or NULL if the function ran out of  
> > > memory.  
> > > \*/  
> > > extern UDPpacket \*SDLNet\_AllocPacket(int size);  
> > > extern void SDLNet\_FreePacket(UDPpacket \*packet);
> > > 
> > > /\* Allocate/Free a UDP packet vector (array of packets) of ‘howmany’  
> > > packets,  
> > > each ‘size’ bytes long.  
> > > A pointer to the first packet in the array is returned, or NULL if  
> > > the  
> > > function ran out of memory.  
> > > \*/  
> > > extern UDPpacket \*\*SDLNet\_AllocPacketV(int howmany, int size);  
> > > extern void SDLNet\_FreePacketV(UDPpacket \*\*packetV);
> > > 
> > > /\* Send a vector of packets to the addresses bound to the given  
> > > channel.  
> > > If ‘channel’ is -1, the packets are broadcast to every address on  
> > > every  
> > > channel bound on the UDP socket.  
> > > This function returns the number of packets sent, or -1 on error.  
> > > \*/  
> > > extern int SDLNet\_SendVUDP(UDPsocket sock, int channel, int howmany,  
> > > UDPpacket \*\*packetV);  
> > > #define SDLNet\_SendUDP(s, c, p) SDLNet\_SendVUDP(s, c, 1, &p)
> > > 
> > > /\* Returns true if the socket is ready to recieve data, blocking for  
> > > up to  
> > > ‘timeout’ milliseconds before returning.  
> > > \*/  
> > > extern int SDLNet\_ReadyUDP(UDPsocket sock, Uint32 timeout);
> > > 
> > > /\* Receive a vector of pending packets from the UDP socket.  
> > > The returned packets contain the source address and the channel  
> > > they  
> > > arrived  
> > > on. If they did not arrive on a bound channel, the the channel  
> > > will be  
> > > set  
> > > to -1.  
> > > This function returns the number of packets read from the network,  
> > > or  
> > > -1  
> > > on error.  
> > > This function does not block, so can return 0 packets pending.  
> > > \*/  
> > > extern int SDLNet\_RecvVUDP(UDPsocket sock, int howmany, UDPpacket  
> > > \*\*packetV);  
> > > #define SDLNet\_RecvUDP(s, p) SDLNet\_SendVUDP(s, 1, &p)
> > > 
> > > /\* Close a UDP network socket \*/  
> > > extern void SDLNet\_CloseUDP(UDPsocket sock);
> 
> /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
> 
> > > /\* Platform-independent data conversion functions  
> > > \*/
> 
> /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
> 
> > > /\* Write a 16/32 bit value to network packet buffer \*/  
> > > extern void Net\_Write16(Uint16 value, Uint8 \*area);  
> > > extern void Net\_Write32(Uint32 value, Uint8 \*area);
> > > 
> > > /\* Read a 16/32 bit value from network packet buffer \*/  
> > > extern Uint16 Net\_Read16(Uint8 \*area);  
> > > extern Uint32 Net\_Read32(Uint8 \*area);
> 
> /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
> 
> > > /\* Error reporting functions  
> > > \*/
> 
> /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
> 
> > > /\* We’ll use SDL’s functions for error reporting \*/  
> > > #define Net\_SetError SDL\_SetError  
> > > #define Net\_GetError SDL\_GetError
> > > 
> > > /\* Ends C function definitions when using C++ _/  
> > > #ifdef \_\_cplusplus  
> > > };  
> > > #endif  
> > > #endif /_ \_SDLnet\_h \*/
> 
> See ya!  
> -Sam Lantinga (slouken at [devolution.com](http://devolution.com))
> 
> ## – Author of Simple DirectMedia Layer - [http://www.devolution.com/~slouken/SDL/](http://www.devolution.com/~slouken/SDL/)

---

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [October 30, 1998, 12:48am UTC](https://discourse.libsdl.org/t/new-api-comments/651/3 "1998-10-30T00:48:15Z")

</div>

You might exceed the MTU, or overfill a buffer.

ICMP unreachable errors are reported in an interesting way.  
I have yet to be able to take advantage of them.

- Dan\> -----Original Message-----

> From: Sam Lantinga [SMTP:slouken at [devolution.com](http://devolution.com)]  
> Sent: Thursday, October 29, 1998 4:40 PM  
> To: Kegel, Dan  
> Subject: Re: New API: Comments?
> 
> > > > 1. The packet buffer should have a status field so that each packet  
> > > > processed by send or receive can have a separate result code, IMHO.  
> > > > Did you catch this one ?-)
> 
> When does a UDP send or recieve fail? Why would some packets fail and  
> others  
> not? ICMP network unreachable type things?
> 
> See ya!  
> -Sam Lantinga (slouken at [devolution.com](http://devolution.com))
> 
> ## – Author of Simple DirectMedia Layer - [http://www.devolution.com/~slouken/SDL/](http://www.devolution.com/~slouken/SDL/)

---

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [November 2, 1998, 7:50pm UTC](https://discourse.libsdl.org/t/new-api-comments/651/4 "1998-11-02T19:50:36Z")

</div>

> Hey, I missed you on Friday… we whipped in and out quick-like.  
> I guess they had plans for lunch. 🙂  
> Yeah, darn.

> Yep. Hey, what do you do for status on a packet that gets sent to multiple  
> channels? Surely you don’t have a two dimensional array, packet x channel?  
> I now doubt that the ‘send same packet to multiple destinations’ feature is  
> good,  
> because a tidy network game will send packets out very carefully  
> to individual destinations as the bandwidth model permits.  
> I retract the suggestion 🙂

I also think your select function misses the boat - you need to provide  
a way to select for activity on multiple udp sockets, don’t think yours  
does at the moment, does it?

- Dan

---

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [November 2, 1998, 8:09pm UTC](https://discourse.libsdl.org/t/new-api-comments/651/5 "1998-11-02T20:09:32Z")

</div>

> _grin_ So you think “send one packet to one destination” is a good model?  
> Nah, send a vector of packets to individual destinations is still a good  
> improvement over that.

> I’ll still add a multi-cast feature “send one packet to all destinations”  
> because it will probably be really useful, and is easy to implement.  
> OK, but IMHO you’re at the wrong level for it, and it won’t get used  
> the way you expect. For instance, I have a handle open to the  
> game server, but I _really_ don’t want to send position packets there.  
> Doing so causes unneeded traffic and therefore extra lag.

> I’m still unsure if I should add the hardware broadcast to a newly opened  
> socket. How often is it actually used?  
> It gets used for all game advertizements when doing local lan stuff.

> How can you guarantee that all clients/peers are on the local lan?  
> Games have two modes: one where they connect to a server to find opponants,  
> one where the LAN acts as the server.

> It seems like it could be easily misunderstood by people who don’t  
> know networking that well, and easily implemented by those who do.  
> Uh, that goes for your whole library 🙂  
> How about having two predefined handles: hardware broadcast  
> and software broadcast, and strongly advising people to use  
> hardware broadcast _only_ for session advertizements, and not  
> for in-game data?

- Dan

---

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [November 2, 1998, 8:09pm UTC](https://discourse.libsdl.org/t/new-api-comments/651/6 "1998-11-02T20:09:50Z")

</div>

Never.\> -----Original Message-----

> From: Sam Lantinga [SMTP:slouken at [devolution.com](http://devolution.com)]  
> Sent: Monday, November 02, 1998 12:01 PM  
> To: Kegel, Dan  
> Subject: Re: New API: Comments?
> 
> > I now doubt that the ‘send same packet to multiple destinations’ feature  
> > is  
> > good, because a tidy network game will send packets out very carefully  
> > to individual destinations as the bandwidth model permits.
> 
> How often does a tidy network game send multiple packets to a single  
> destination at once?
> 
> See ya!  
> -Sam Lantinga (slouken at [devolution.com](http://devolution.com))
> 
> ## – Author of Simple DirectMedia Layer - [http://www.devolution.com/~slouken/SDL/](http://www.devolution.com/~slouken/SDL/)

---

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [November 2, 1998, 8:27pm UTC](https://discourse.libsdl.org/t/new-api-comments/651/7 "1998-11-02T20:27:32Z")

</div>

A vector of packets to different destinations.  
The vector consists of structures of the form

int channel; /\* the source or destination _/  
int status; /_ the result of the send or get operation \*/  
int len;  
char \*buf;

These structures are used in both send\_v and recv\_v.

- Dan\> -----Original Message-----

> From: Sam Lantinga [SMTP:slouken at [devolution.com](http://devolution.com)]  
> Sent: Monday, November 02, 1998 12:16 PM  
> To: Kegel, Dan  
> Subject: Re: New API: Comments?
> 
> If that’s true, then why would you support sending a vector of packets?  
> Am I misunderstanding what you mean by a vector of packets?
> 
> > Never.
> 
> > > -----Original Message-----  
> > > From: Sam Lantinga [SMTP:slouken at [devolution.com](http://devolution.com)]  
> > > Sent: Monday, November 02, 1998 12:01 PM  
> > > To: Kegel, Dan  
> > > Subject: Re: New API: Comments?
> > > 
> > > > I now doubt that the ‘send same packet to multiple destinations’  
> > > > feature  
> > > > is  
> > > > good, because a tidy network game will send packets out very  
> > > > carefully  
> > > > to individual destinations as the bandwidth model permits.
> > > 
> > > How often does a tidy network game send multiple packets to a single  
> > > destination at once?
> > > 
> > > See ya!  
> > > -Sam Lantinga (slouken at [devolution.com](http://devolution.com))
> > > 
> > > ## – Author of Simple DirectMedia Layer - [http://www.devolution.com/~slouken/SDL/](http://www.devolution.com/~slouken/SDL/)
> 
> See ya!  
> -Sam Lantinga (slouken at [devolution.com](http://devolution.com))
> 
> ## – Author of Simple DirectMedia Layer - [http://www.devolution.com/~slouken/SDL/](http://www.devolution.com/~slouken/SDL/)

---

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [November 2, 1998, 8:54pm UTC](https://discourse.libsdl.org/t/new-api-comments/651/8 "1998-11-02T20:54:39Z")

</div>

You catch on fast, kimosabe.

- Dan\> -----Original Message-----

> From: Sam Lantinga [SMTP:slouken at [devolution.com](http://devolution.com)]  
> Sent: Monday, November 02, 1998 12:50 PM  
> To: Kegel, Dan  
> Subject: Re: New API: Comments?
> 
> I’m confused. I asked “When does a tidy network game send multiple  
> packets to a single destination?” and you said “Never”. Isn’t sending  
> a vector of packets to a destination the same as sending multiple packets  
> to a destination? Oh… I see. 🙂 The trick is you never actually  
> specify the destination in the function call, you just look at the packet  
> vector. That way you can do a high level loop to send packets to multiple  
> destinations, or send multiple packets to the same destination all at  
> once.
> 
> Very cool. 🙂
> 
> > A vector of packets to different destinations.  
> > The vector consists of structures of the form
> 
> > int channel; /\* the source or destination _/  
> > int status; /_ the result of the send or get operation \*/  
> > int len;  
> > char \*buf;
> 
> > These structures are used in both send\_v and recv\_v.
> > 
> > - Dan
> 
> > > -----Original Message-----  
> > > From: Sam Lantinga [SMTP:slouken at [devolution.com](http://devolution.com)]  
> > > Sent: Monday, November 02, 1998 12:16 PM  
> > > To: Kegel, Dan  
> > > Subject: Re: New API: Comments?
> > > 
> > > If that’s true, then why would you support sending a vector of  
> > > packets?  
> > > Am I misunderstanding what you mean by a vector of packets?
> > > 
> > > > Never.
> > > 
> > > > > -----Original Message-----  
> > > > > From: Sam Lantinga [SMTP:slouken at [devolution.com](http://devolution.com)]  
> > > > > Sent: Monday, November 02, 1998 12:01 PM  
> > > > > To: Kegel, Dan  
> > > > > Subject: Re: New API: Comments?
> > > > > 
> > > > > > I now doubt that the ‘send same packet to multiple destinations’  
> > > > > > feature  
> > > > > > is  
> > > > > > good, because a tidy network game will send packets out very  
> > > > > > carefully  
> > > > > > to individual destinations as the bandwidth model permits.
> > > > > 
> > > > > How often does a tidy network game send multiple packets to a  
> > > > > single  
> > > > > destination at once?
> > > > > 
> > > > > See ya!  
> > > > > -Sam Lantinga  
> > > > > (slouken at [devolution.com](http://devolution.com))
> > > > > 
> > > > > ## – Author of Simple DirectMedia Layer - [http://www.devolution.com/~slouken/SDL/](http://www.devolution.com/~slouken/SDL/)
> > > 
> > > See ya!  
> > > -Sam Lantinga (slouken at [devolution.com](http://devolution.com))
> > > 
> > > ## – Author of Simple DirectMedia Layer - [http://www.devolution.com/~slouken/SDL/](http://www.devolution.com/~slouken/SDL/)
> 
> See ya!  
> -Sam Lantinga (slouken at [devolution.com](http://devolution.com))
> 
> ## – Author of Simple DirectMedia Layer - [http://www.devolution.com/~slouken/SDL/](http://www.devolution.com/~slouken/SDL/)

---

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [November 2, 1998, 9:51pm UTC](https://discourse.libsdl.org/t/new-api-comments/651/9 "1998-11-02T21:51:11Z")

</div>

It be bad to have multiple-statement macros.  
if (x)  
send;  
else  
dflka

doesn’t work too well in that case. Better make it a thin function.

- Dan\> -----Original Message-----

> From: Sam Lantinga [SMTP:slouken at [devolution.com](http://devolution.com)]  
> Sent: Monday, November 02, 1998 1:12 PM  
> To: Kegel, Dan  
> Subject: Re: New API: Comments?
> 
> > You catch on fast, kimosabe.
> 
> Er, thanks… :-}
> 
> I didn’t think about using the channel for the destination in outbound  
> packets. 🙂 I think I’ll make send(c, p) be: p-\>c = c; send\_v(&p, 1)
> 
> See ya!  
> -Sam Lantinga (slouken at [devolution.com](http://devolution.com))
> 
> ## – Author of Simple DirectMedia Layer - [http://www.devolution.com/~slouken/SDL/](http://www.devolution.com/~slouken/SDL/)

---

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [November 2, 1998, 9:57pm UTC](https://discourse.libsdl.org/t/new-api-comments/651/10 "1998-11-02T21:57:08Z")

</div>

[http://lwn.net/daily/corel.html](http://lwn.net/daily/corel.html)

I forgot about winelib, but Corel seems to be a big believer in it.

- Dan

---

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [November 2, 1998, 10:19pm UTC](https://discourse.libsdl.org/t/new-api-comments/651/11 "1998-11-02T22:19:26Z")

</div>

> typedef struct {  
> int ready;  
> } \*SDLNet\_Socket;

mmm. I’m confused about that typedef.  
Shouldn’t you have a typedef for sdlnet\_socketset?

> #define SDLNet\_AddSocket(set, n, sock) {   
> set[n] = (SDLNet\_Socket) sock;   
> }  
> I’m confused. I thought ready contained a boolean, not a socket number?

> extern int SDLNet\_CheckSockets(SDLNet\_Socket \*set, Uint32 timeout);  
> OK.

> #define SDLNet\_SocketReady(sock) (((SDLNet\_Socket)sock)-\>ready)  
> OK.

it’d be nice to have a way to copy a socketset, so you didn’t have to  
keep building one from scratch, maybe.

- Dan

---

<div class="post-metadata">

**Author:** ![Kegel\_Dan](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/k/a6a055/32.png) [@Kegel\_Dan](https://discourse.libsdl.org/u/Kegel_Dan)\
**Post date:** [November 2, 1998, 10:31pm UTC](https://discourse.libsdl.org/t/new-api-comments/651/12 "1998-11-02T22:31:29Z")

</div>

That looks good.\> -----Original Message-----

> From: Sam Lantinga [SMTP:slouken at [devolution.com](http://devolution.com)]  
> Sent: Monday, November 02, 1998 2:24 PM  
> To: Kegel, Dan  
> Subject: Re: New API: Comments?
> 
> > mmm. I’m confused about that typedef.  
> > Shouldn’t you have a typedef for sdlnet\_socketset?
> 
> Yeah, probably. I was making SDLNet\_AddSocket() into a macro, but  
> that’s a bit confusing and not necessary for speed. I’ll demonstrate  
> in the example that follows…
> 
> > it’d be nice to have a way to copy a socketset, so you didn’t have to  
> > keep building one from scratch, maybe.
> 
> You won’t need to:
> 
> gameinit(int maxsockets)  
> {  
> set = SDLNet\_AllocSocketSet(maxsockets);  
> }
> 
> netinit(sock1, sock2) {  
> SDLNet\_TCP\_AddSocket(set, sock1);  
> SDLNet\_UDP\_AddSocket(set, sock2);  
> }
> 
> while (game\_running) {  
> while ( SDLNet\_CheckSockets(set, 0) ) {  
> if ( SDLNet\_SocketReady(sock1) ) {  
> // Handle control message  
> }  
> if ( SDLNet\_SocketReady(sock2) ) {  
> // Handle update packet  
> }  
> }  
> }
> 
> cleanup() {  
> SDLNet\_FreeSocketSet(set);  
> }
> 
> Note the changed API… I’ll also need SDLNet\_TCP\_DelSocket(), but the  
> point  
> is that you only need to create the socket set once, and keep using it in  
> the CheckSockets() call.
> 
> See ya!  
> -Sam Lantinga (slouken at [devolution.com](http://devolution.com))
> 
> ## – Author of Simple DirectMedia Layer - [http://www.devolution.com/~slouken/SDL/](http://www.devolution.com/~slouken/SDL/)
