1 /* -*- Mode: C++; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*-
2  *
3  * Quadra, an action puzzle game
4  * Copyright (C) 1998-2000  Ludus Design
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 
21 #ifndef _HEADER_NET
22 #define _HEADER_NET
23 
24 #include <list>
25 #include <vector>
26 
27 #include "config.h"
28 
29 #ifdef UGS_DIRECTX
30 #include "winsock.h"
31 #endif
32 
33 #ifdef UGS_LINUX
34 #include <errno.h>
35 #ifndef __STRICT_ANSI__
36 #define I_SET_STRICT_ANSI
37 #define __STRICT_ANSI__
38 #endif
39 #include <sys/socket.h>
40 #ifdef I_SET_STRICT_ANSI
41 #undef I_SET_STRICT_ANSI
42 #undef __STRICT_ANSI__
43 #endif
44 #include <sys/time.h>
45 #include <netinet/in.h>
46 #define SOCKET_ERROR -1
47 #endif
48 
49 const unsigned NETBUF_SIZE = 4096;
50 
51 #include "types.h"
52 #include "packet.h"
53 #include "notify.h"
54 #include "net_call.h"
55 #include "id.h"
56 #include "buf.h"
57 
58 class IP_addr {
59 public:
60 	Dword ip, mask;
61 	IP_addr(const IP_addr& o);
62 	IP_addr(const char *addr);
63 	IP_addr(Dword pip, Dword pmask=0xFFFFFFFF);
64 	void print(char *st);
65 	bool operator>(const IP_addr& o);
66 	bool operator>=(const IP_addr& o);
67 	void set(const char *addr);
68 	void set(Dword pip, Dword pmask);
69 };
70 
71 class Net_buf;
72 class Net_connection;
73 class Net_connection_tcp;
74 
75 class Packet;
76 
77 class Net_param {
78 public:
79 	virtual bool accept_connection(Net_connection *nc);
server_deconnect()80 	virtual void server_deconnect() { } // handle event in case of server disconnection
client_connect(Net_connection * adr)81 	virtual void client_connect(Net_connection *adr) { }
client_deconnect(Net_connection * adr)82 	virtual void client_deconnect(Net_connection *adr) { } // handle event in case of a client disconnection (on server only)
83 	virtual int tcpport()=0;
udpport()84 	virtual int udpport() {
85 		return tcpport()+1;
86 	}
87 	virtual void print_packet(Packet *p2, char *st)=0;
88 	virtual Packet *alloc_packet(Word pt)=0;
is_dispatchable(Net_connection * nc,Packet * p)89 	virtual bool is_dispatchable(Net_connection *nc, Packet *p) {
90 		return true;
91 	}
92 	virtual Dword magic()=0;
get_motd()93 	virtual const char *get_motd() {
94 		return "Hello!";
95 	}
~Net_param()96 	virtual ~Net_param() {
97 	}
98 };
99 
100 class Exec_ping: public Net_callable {
101 	static Dword next_uid;
102 	Net_connection *dest;
103 	Word type;
104 	Dword uid;
105 	Net_callable *net_callable;
106 public:
107 	//default d to 0 for clients
108 	Exec_ping(Packet_ping *p, Word pt, Net_callable *netc, Net_connection *d=NULL);
109 	virtual ~Exec_ping();
110 	virtual void net_call(Packet *p2);
111 	virtual bool validate(Packet_ping *p2);
112 };
113 
114 class Buf;
115 
116 class Net_connection: public Identifyable {
117 public:
118 	enum Netstate {
119 		invalid, valid, waitingfordns, dnslookup, connecting, connected, disconnected
120 	};
121 	bool packet_based;
122 	bool joined;
123 	bool trusted;
124 	Dword incoming_inactive;
125 	Dword outgoing_inactive;
126 	Dword outgoing_size;
127 	Dword outgoing_min;
128 	Dword outgoing_max;
129 	Dword outgoing_total;
130 	Dword incoming_size;
131 	Dword incoming_min;
132 	Dword incoming_max;
133 	Dword incoming_total;
134 	Dword commit_count_in;
135 	Dword commit_count_out;
136 	Dword commit_count_both;
137 	Dword commit_count_total;
138 	Buf *incoming; //Set only when !packet_based
139 	virtual Netstate state();
140 	virtual void connect(Net_connection *dest);
141 	virtual void connect(Dword adr, int port);
142 	virtual void connect(const char* host, int port);
143 	virtual bool checktcp();
144 	virtual void receivetcp(Net_buf *p);
145 	virtual int receivetcp(Byte *buf, Dword size);
146 	virtual void sendtcp(Packet *p2);
147 	virtual void sendtcp(const Byte *buf, Dword size);
148 	virtual void commit();
149 	virtual void disconnect();
address()150 	virtual Dword address() const {
151 		return INADDR_LOOPBACK;
152 	}
getdestaddr()153 	virtual Dword getdestaddr() const {
154 		return INADDR_LOOPBACK;
155 	}
getdestport()156 	virtual int getdestport() const {
157 		return destport;
158 	}
159 	virtual Dword getbufsize() const;
getFD()160 	virtual int getFD() const {
161 		return -1;
162 	}
163 	Net_connection();
164 	virtual ~Net_connection();
165 protected:
166 	int destport;
167 	Netstate _state;
168 private:
169 	static int next_port;
170 	Buf *buf;
171 	Net_connection *connected_to;
172 };
173 
174 class Net_connection_tcp: public Net_connection {
175 private:
176 	friend class Net;
177 	int tcpsock;
178 	Dword from;
179 	sockaddr_in tcpsin;
180 	Byte tcpbuf[NETBUF_SIZE+2];
181 	Dword tcpbufsize;
182 	Dword tcppacsize;
183 	char desthost[256];
184 	Dword destaddr;
185 	int destport;
186 	Buf outgoing_buf;
187 public:
188 	Net_connection_tcp(int p=0, bool ppacket_based=true);
189 	Net_connection_tcp(int sock, Dword adr, int port, bool ppacket_based=true);
190 	virtual ~Net_connection_tcp();
191 	virtual Netstate state();
192 	virtual void connect(Dword adr, int port);
193 	virtual void connect(const char* host, int port);
194 	virtual bool checktcp();
195 	virtual void receivetcp(Net_buf *p);
196 	virtual int receivetcp(Byte *buf, Dword size);
197 	virtual void sendtcp(Packet *p);
198 	virtual void sendtcp(const Byte *buf, Dword size);
199 	virtual void commit();
address()200 	virtual Dword address() const {
201 		return from;
202 	}
getdestaddr()203 	virtual Dword getdestaddr() const {
204 		return destaddr;
205 	}
getdesthost()206 	virtual const char* getdesthost() const {
207 		return desthost;
208 	}
getdestport()209 	virtual int getdestport() const {
210 		return destport;
211 	}
getbufsize()212 	virtual Dword getbufsize() const {
213 		return tcpbufsize;
214 	}
215 	virtual int getFD() const;
216 };
217 
218 class Http_request;
219 
220 class Net: public Observable {
221 public:
222 	std::vector<Net_connection*> connections;
223 	bool active;
224 	const char *last_error;
225 	Dword name_resolve;
226 	int port_resolve;
227 	char host_name[1024];
228 	// All the IP addresses of this machine
229 	std::vector<Dword> host_adr;
230 	// Those IP addresses that look like public internet addresses
231 	std::vector<Dword> host_adr_pub;
232 
233 	Net_param *net_param;
234 
235 	Net(Net_param *np);
236 	virtual ~Net();
237 
238 	//Client+Server
239 	Net_connection *server_addr();
240 	void step(bool loop_only=false);
241 	void addwatch(Word id, Net_callable *nc);
242 	void removewatch(Word id, Net_callable *nc);
243 	void sendudp(Dword to, Packet *p);
244 
245 	//Server
246 	void start_server(bool sock);
247 	void stop_server();
248 	void suspend_server();
249 	void sendtcp(Net_connection *nc, Packet *p);
250 	void dispatch(Packet *p, Dword pt, Net_connection *nc=NULL);
251 
252 	//Client
253 	Net_connection *start_loopback_client();
254 	void start_client(Dword adr, int port=0);
255 	void stop_client();
256 	bool connected();
257 	void sendtcp(Packet *p);
258 
259 	//All-purpose as long as TCP/IP is there :)
260 	Net_connection_tcp *start_other(Dword adr, int port);
261 	Net_connection_tcp *start_other(const char *host, int port);
262 
263 	//Utils
264 	Packet *net_buf2packet(Net_buf *nb, bool tcp);
265 
266 	static Dword dotted2addr(const char *host);
267 	static void stringaddress(char *st, Dword adr);
268 	static void stringaddress(char *st, Dword adr, int port);
269 
270 	Dword getaddress(const char *host);
271 	void gethostbyname_completed(bool success);
272 	void gethostbyname_cancel();
273 	const char *failed();
274 	void init_local_addresses();
275 	void init_all_udp();
276 	void close_all_udp();
277 private:
278 	friend class Net_connection_tcp;
279 	friend class Net_connection;
280 	Net_connection *server_connection;
281 	Net_connection *client_connection;
282 
283 	friend class Packet_udp;
284 
285 	class Net_receive_cb {
286 	public:
287 		Word id;
288 		Net_callable *net_callable;
Net_receive_cb(Word i,Net_callable * nc)289 		Net_receive_cb(Word i, Net_callable *nc) {
290 			id = i;
291 			net_callable = nc;
292 		}
293 	};
294 	std::list<Net_receive_cb*> callbacks;
295 
296 	int udpsock[32], udpport, udpnum;
297 	sockaddr_in udpsin;
298 
299 	void packetreceived(Net_buf *nb, bool tcp);
300 
301 	int checkreceive(int s);
302 	void receiveudp(int sock, Net_buf *p);
303 	bool accept();
304 	int open_udpsock(Dword adr);
305 	void verify_connections();
306 	void verify_server_connection();
307 
308 	/* true if error (message in last_error) */
309 	bool checkerror(int quel);
310 	/* verifies if extended error in WSALasterror or errno */
311 	bool getlasterror(int quel);
312 	/* quits with an error message */
313 	void callwsa(int quel);
314 
315 	#ifdef UGS_DIRECTX
316 		char name_buf[MAXGETHOSTSTRUCT];
317 		HANDLE name_handle;
318 	#endif
319 };
320 
321 extern Net* net;
322 
323 #endif
324