diff options
Diffstat (limited to 'src/KINDLE/i_network.c')
-rw-r--r-- | src/KINDLE/i_network.c | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/src/KINDLE/i_network.c b/src/KINDLE/i_network.c new file mode 100644 index 0000000..4730d50 --- /dev/null +++ b/src/KINDLE/i_network.c | |||
@@ -0,0 +1,292 @@ | |||
1 | /* Emacs style mode select -*- C++ -*- | ||
2 | *----------------------------------------------------------------------------- | ||
3 | * | ||
4 | * | ||
5 | * PrBoom: a Doom port merged with LxDoom and LSDLDoom | ||
6 | * based on BOOM, a modified and improved DOOM engine | ||
7 | * Copyright (C) 1999 by | ||
8 | * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman | ||
9 | * Copyright (C) 1999-2000 by | ||
10 | * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze | ||
11 | * Copyright 2005, 2006 by | ||
12 | * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version 2 | ||
17 | * of the License, or (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
27 | * 02111-1307, USA. | ||
28 | * | ||
29 | * DESCRIPTION: | ||
30 | * Low level UDP network interface. This is shared between the server | ||
31 | * and client, with SERVER defined for the former to select some extra | ||
32 | * functions. Handles socket creation, and packet send and receive. | ||
33 | * | ||
34 | *-----------------------------------------------------------------------------*/ | ||
35 | |||
36 | #ifdef HAVE_CONFIG_H | ||
37 | # include "config.h" | ||
38 | #endif | ||
39 | #ifdef HAVE_NETINET_IN_H | ||
40 | # include <netinet/in.h> | ||
41 | #endif | ||
42 | #include <stdlib.h> | ||
43 | #include <errno.h> | ||
44 | #ifdef HAVE_UNISTD_H | ||
45 | #include <unistd.h> | ||
46 | #endif | ||
47 | #include <stdio.h> | ||
48 | #include <fcntl.h> | ||
49 | #include <string.h> | ||
50 | |||
51 | #ifdef HAVE_NET | ||
52 | |||
53 | #include "SDL.h" | ||
54 | #include "SDL_net.h" | ||
55 | |||
56 | #include "protocol.h" | ||
57 | #include "i_network.h" | ||
58 | #include "lprintf.h" | ||
59 | //#include "doomstat.h" | ||
60 | |||
61 | /* cph - | ||
62 | * Each client will either use the IPv4 socket or the IPv6 socket | ||
63 | * Each server will use whichever or both that are available | ||
64 | */ | ||
65 | UDP_CHANNEL sentfrom; | ||
66 | IPaddress sentfrom_addr; | ||
67 | UDP_SOCKET udp_socket; | ||
68 | |||
69 | /* Statistics */ | ||
70 | size_t sentbytes, recvdbytes; | ||
71 | |||
72 | UDP_PACKET *udp_packet; | ||
73 | |||
74 | /* I_ShutdownNetwork | ||
75 | * | ||
76 | * Shutdown the network code | ||
77 | */ | ||
78 | void I_ShutdownNetwork(void) | ||
79 | { | ||
80 | SDLNet_FreePacket(udp_packet); | ||
81 | SDLNet_Quit(); | ||
82 | } | ||
83 | |||
84 | /* I_InitNetwork | ||
85 | * | ||
86 | * Sets up the network code | ||
87 | */ | ||
88 | void I_InitNetwork(void) | ||
89 | { | ||
90 | SDLNet_Init(); | ||
91 | atexit(I_ShutdownNetwork); | ||
92 | udp_packet = SDLNet_AllocPacket(10000); | ||
93 | } | ||
94 | |||
95 | UDP_PACKET *I_AllocPacket(int size) | ||
96 | { | ||
97 | return(SDLNet_AllocPacket(size)); | ||
98 | } | ||
99 | |||
100 | void I_FreePacket(UDP_PACKET *packet) | ||
101 | { | ||
102 | SDLNet_FreePacket(packet); | ||
103 | } | ||
104 | |||
105 | |||
106 | /* cph - I_WaitForPacket - use select(2) via SDL_net's interface | ||
107 | * No more I_uSleep loop kludge */ | ||
108 | |||
109 | void I_WaitForPacket(int ms) | ||
110 | { | ||
111 | SDLNet_SocketSet ss = SDLNet_AllocSocketSet(1); | ||
112 | SDLNet_UDP_AddSocket(ss, udp_socket); | ||
113 | SDLNet_CheckSockets(ss,ms); | ||
114 | SDLNet_FreeSocketSet(ss); | ||
115 | #if (defined _WIN32 && !defined PRBOOM_SERVER) | ||
116 | I_UpdateConsole(); | ||
117 | #endif | ||
118 | } | ||
119 | |||
120 | /* I_ConnectToServer | ||
121 | * | ||
122 | * Connect to a server | ||
123 | */ | ||
124 | IPaddress serverIP; | ||
125 | |||
126 | int I_ConnectToServer(const char *serv) | ||
127 | { | ||
128 | char server[500], *p; | ||
129 | Uint16 port; | ||
130 | |||
131 | /* Split serv into address and port */ | ||
132 | if (strlen(serv)>500) return 0; | ||
133 | strcpy(server,serv); | ||
134 | p = strchr(server, ':'); | ||
135 | if(p) | ||
136 | { | ||
137 | *p++ = '\0'; | ||
138 | port = atoi(p); | ||
139 | } | ||
140 | else | ||
141 | port = 5030; /* Default server port */ | ||
142 | |||
143 | SDLNet_ResolveHost(&serverIP, server, port); | ||
144 | if ( serverIP.host == INADDR_NONE ) | ||
145 | return -1; | ||
146 | |||
147 | if (SDLNet_UDP_Bind(udp_socket, 0, &serverIP) == -1) | ||
148 | return -1; | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | /* I_Disconnect | ||
154 | * | ||
155 | * Disconnect from server | ||
156 | */ | ||
157 | void I_Disconnect(void) | ||
158 | { | ||
159 | /* int i; | ||
160 | UDP_PACKET *packet; | ||
161 | packet_header_t *pdata = (packet_header_t *)packet->data; | ||
162 | packet = I_AllocPacket(sizeof(packet_header_t) + 1); | ||
163 | |||
164 | packet->data[sizeof(packet_header_t)] = consoleplayer; | ||
165 | pdata->type = PKT_QUIT; pdata->tic = gametic; | ||
166 | |||
167 | for (i=0; i<4; i++) { | ||
168 | I_SendPacket(packet); | ||
169 | I_uSleep(10000); | ||
170 | } | ||
171 | I_FreePacket(packet);*/ | ||
172 | SDLNet_UDP_Unbind(udp_socket, 0); | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * I_Socket | ||
177 | * | ||
178 | * Sets the given socket non-blocking, binds to the given port, or first | ||
179 | * available if none is given | ||
180 | */ | ||
181 | UDP_SOCKET I_Socket(Uint16 port) | ||
182 | { | ||
183 | if(port) | ||
184 | return (SDLNet_UDP_Open(port)); | ||
185 | else { | ||
186 | UDP_SOCKET sock; | ||
187 | port = IPPORT_RESERVED; | ||
188 | while( (sock = SDLNet_UDP_Open(port)) == NULL ) | ||
189 | port++; | ||
190 | return sock; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | void I_CloseSocket(UDP_SOCKET sock) | ||
195 | { | ||
196 | SDLNet_UDP_Close(sock); | ||
197 | } | ||
198 | |||
199 | UDP_CHANNEL I_RegisterPlayer(IPaddress *ipaddr) | ||
200 | { | ||
201 | static int freechannel; | ||
202 | return(SDLNet_UDP_Bind(udp_socket, freechannel++, ipaddr)); | ||
203 | } | ||
204 | |||
205 | void I_UnRegisterPlayer(UDP_CHANNEL channel) | ||
206 | { | ||
207 | SDLNet_UDP_Unbind(udp_socket, channel); | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * ChecksumPacket | ||
212 | * | ||
213 | * Returns the checksum of a given network packet | ||
214 | */ | ||
215 | static byte ChecksumPacket(const packet_header_t* buffer, size_t len) | ||
216 | { | ||
217 | const byte* p = (const void*)buffer; | ||
218 | byte sum = 0; | ||
219 | |||
220 | if (len==0) | ||
221 | return 0; | ||
222 | |||
223 | while (p++, --len) | ||
224 | sum += *p; | ||
225 | |||
226 | return sum; | ||
227 | } | ||
228 | |||
229 | size_t I_GetPacket(packet_header_t* buffer, size_t buflen) | ||
230 | { | ||
231 | int checksum; | ||
232 | size_t len; | ||
233 | int status; | ||
234 | |||
235 | status = SDLNet_UDP_Recv(udp_socket, udp_packet); | ||
236 | len = udp_packet->len; | ||
237 | if (buflen<len) | ||
238 | len=buflen; | ||
239 | if ( (status!=0) && (len>0) ) | ||
240 | memcpy(buffer, udp_packet->data, len); | ||
241 | sentfrom=udp_packet->channel; | ||
242 | #ifndef SDL_NET_UDP_PACKET_SRC | ||
243 | sentfrom_addr=udp_packet->address; | ||
244 | #else | ||
245 | sentfrom_addr=udp_packet->src; /* cph - allow for old SDL_net library */ | ||
246 | #endif | ||
247 | checksum=buffer->checksum; | ||
248 | buffer->checksum=0; | ||
249 | if ( (status!=0) && (len>0)) { | ||
250 | byte psum = ChecksumPacket(buffer, udp_packet->len); | ||
251 | /* fprintf(stderr, "recvlen = %u, stolen = %u, csum = %u, psum = %u\n", | ||
252 | udp_packet->len, len, checksum, psum); */ | ||
253 | if (psum == checksum) return len; | ||
254 | } | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | void I_SendPacket(packet_header_t* packet, size_t len) | ||
259 | { | ||
260 | packet->checksum = ChecksumPacket(packet, len); | ||
261 | memcpy(udp_packet->data, packet, udp_packet->len = len); | ||
262 | SDLNet_UDP_Send(udp_socket, 0, udp_packet); | ||
263 | } | ||
264 | |||
265 | void I_SendPacketTo(packet_header_t* packet, size_t len, UDP_CHANNEL *to) | ||
266 | { | ||
267 | packet->checksum = ChecksumPacket(packet, len); | ||
268 | memcpy(udp_packet->data, packet, udp_packet->len = len); | ||
269 | SDLNet_UDP_Send(udp_socket, *to, udp_packet); | ||
270 | } | ||
271 | |||
272 | void I_PrintAddress(FILE* fp, UDP_CHANNEL *addr) | ||
273 | { | ||
274 | /* | ||
275 | char *addy; | ||
276 | Uint16 port; | ||
277 | IPaddress *address; | ||
278 | |||
279 | address = SDLNet_UDP_GetPeerAddress(udp_socket, player); | ||
280 | |||
281 | //FIXME: if it cant resolv it may freeze up | ||
282 | addy = SDLNet_ResolveIP(address); | ||
283 | port = address->port; | ||
284 | |||
285 | if(addy != NULL) | ||
286 | fprintf(fp, "%s:%d", addy, port); | ||
287 | else | ||
288 | fprintf(fp, "Error"); | ||
289 | */ | ||
290 | } | ||
291 | |||
292 | #endif /* HAVE_NET */ | ||