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