- 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,
- 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().
-
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 -
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. -
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.
- 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]
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 © 1997 Sam LantingaThis 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 4typedef 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 */