console: Format tabs semi-intelligently
[attac-man.git] / net.c
bloba10ea1cebfcfd8412ad9dc37998d5167f387b716
1 /*
2 Pacman Arena
3 Copyright (C) 2003 Nuno Subtil
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 static const char cvsid[] =
21 "$Id: net.c,v 1.4 2003/11/27 22:39:11 nsubtil Exp $";
23 #include "config.h"
25 #include <SDL_net.h>
26 #include <stdlib.h>
28 #include "audio.h"
29 #include "net.h"
31 static UDPsocket sock = NULL;
32 static IPaddress srv_addr;
33 static UDPpacket *packet = NULL;
35 int server_running = 0;
36 int client_running = 0;
39 starts a listener for the network server
41 void net_server_init(void)
43 if(sock == NULL)
44 SDLNet_Init();
46 sock = SDLNet_UDP_Open(NET_PACMAN_PORT);
47 if(sock == NULL)
49 printf("net_server_init: SDLNet_UDP_Open: %s\n", SDLNet_GetError());
50 SDL_Quit();
51 exit(1);
54 if(packet == NULL)
56 packet = SDLNet_AllocPacket(NET_MAX_PACKET_SIZE);
57 if(packet == NULL)
59 printf("net_send_packet: SDLNet_AllocPacket: %s\n", SDLNet_GetError());
60 SDL_Quit();
61 exit(1);
65 printf("net_server_init: listening on port %d\n", NET_PACMAN_PORT);
66 server_running = 1;
70 connects to a server on a given host
72 void net_client_init(char *hostname)
74 struct packet_r_connok p;
76 if(packet == NULL)
78 SDLNet_Init();
79 packet = SDLNet_AllocPacket(NET_MAX_PACKET_SIZE);
80 if(packet == NULL)
82 printf("net_send_packet: SDLNet_AllocPacket: %s\n", SDLNet_GetError());
83 SDL_Quit();
84 exit(1);
88 sock = SDLNet_UDP_Open(0);
89 if(sock == NULL)
91 printf("net_client_init: SDLNet_UDP_Open: %s\n", SDLNet_GetError());
92 SDL_Quit();
93 exit(1);
96 if(SDLNet_ResolveHost(&srv_addr, hostname, NET_PACMAN_PORT) == -1)
98 printf("net_client_init: SDLNet_ResolveHost(%s): %s\n", hostname, SDLNet_GetError());
99 SDL_Quit();
100 exit(1);
103 if(SDLNet_UDP_Bind(sock, 0, &srv_addr) == -1)
105 printf("net_client_init: SDLNet_UDP_Bind: %s\n", SDLNet_GetError());
106 SDL_Quit();
107 exit(1);
110 printf("net_client_init: connecting to %s port %d...\n", hostname, NET_PACMAN_PORT);
111 /* send a connection packet */
112 net_send_packet(sock, PTYPE_REQ_NEWCONN, NULL, srv_addr);
113 /* wait for reply */
114 net_wait_packet(sock, packet);
116 if(net_decode_ptype(packet) != PTYPE_REPLY_CONNOK)
118 printf("net_client_init: connection refused\n");
119 SDL_Quit();
120 exit(1);
123 net_decode_pdata(packet, &p);
124 printf("net_client_init: connection established, id %d\n", p.player_id);
126 client_running = 1;
130 waits for a packet
132 void net_wait_packet(UDPsocket usock, UDPpacket *pack)
134 while(SDLNet_UDP_Recv(usock, pack) != 1)
135 SDL_Delay(1);
139 builds and sends a packet of a given type to a destination
141 void net_send_packet(UDPsocket usock, Uint8 ptype, void *pdata, IPaddress dest)
143 packet->len = 0;
144 net_encode(packet, ptype, pdata);
145 packet->address = dest;
146 if(SDLNet_UDP_Send(usock, -1, packet) == 0)
148 printf("net_send_packet: SDLNet_UDP_Send: %s\n", SDLNet_GetError());
149 SDL_Quit();
150 exit(1);
155 encodes a packet of a given type
157 void net_encode(UDPpacket *pack, Uint8 ptype, void *pdata)
160 packet structure:
161 - packet type (1 byte)
162 - packet flags (1 byte)
163 - packet data (variable)
166 /* packet type */
167 net_pack_byte(pack, ptype);
168 /* packet flags */
169 net_pack_byte(pack, 0);
171 switch(ptype)
173 case PTYPE_REQ_NEWCONN:
174 /* nothing */
175 break;
177 case PTYPE_REPLY_CONNOK:
179 struct packet_r_connok *p;
181 p = (struct packet_r_connok *)pdata;
182 net_pack_int32(pack, p->player_id);
184 break;
187 default:
188 printf("net_send_packet: unknown ptype %d\n", ptype);
189 SDL_Quit();
190 exit(1);
195 decodes the packet type
196 returns the type of packet, or -1 on error
198 int net_decode_ptype(UDPpacket *pack)
200 switch(pack->data[0])
202 case PTYPE_REQ_NEWCONN:
203 return PTYPE_REQ_NEWCONN;
205 case PTYPE_REPLY_CONNOK:
206 return PTYPE_REPLY_CONNOK;
208 default:
209 return -1;
214 decodes the data in pack
216 void net_decode_pdata(UDPpacket *pack, void *data)
218 switch(pack->data[0])
220 case PTYPE_REQ_NEWCONN:
221 return;
223 case PTYPE_REPLY_CONNOK:
225 struct packet_r_connok *p;
227 p = (struct packet_r_connok *)data;
229 p->player_id = SDLNet_Read32(&pack->data[2]);
231 return;
237 packs a byte on the end of a packet
239 void net_pack_byte(UDPpacket *pack, Uint8 value)
241 if(pack->len + 1 > pack->maxlen)
243 printf("net_pack_byte: packet too small (%d)\n", pack->maxlen);
244 SDL_Quit();
245 exit(1);
248 pack->data[pack->len] = value;
249 pack->len++;
253 packs a 32-bit value on the end of a packet
255 void net_pack_int32(UDPpacket *pack, Uint32 value)
257 if(pack->len + 4 > pack->maxlen)
259 printf("net_pack_int32: packet too small (%d)\n", pack->maxlen);
260 SDL_Quit();
261 exit(1);
264 SDLNet_Write32(value, &pack->data[pack->len]);
265 pack->len += 4;
269 updates the server
271 void net_server_update(void)
273 while(SDLNet_UDP_Recv(sock, packet) == 1)
275 switch(net_decode_ptype(packet))
277 case PTYPE_REQ_NEWCONN:
279 struct packet_r_connok p = {1};
281 printf("net_server_update: new connection from %s\n", SDLNet_ResolveIP(&packet->address));
282 audio_play_sample("sfx/ghost-return.wav");
283 net_send_packet(sock, PTYPE_REPLY_CONNOK, &p, packet->address);
290 updates the client
292 void net_client_update(void)