[555] | 1 | /* |
---|
| 2 | * Abuse - dark 2D side-scrolling platform game |
---|
| 3 | * Copyright (c) 1995 Crack dot Com |
---|
| 4 | * Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net> |
---|
| 5 | * |
---|
| 6 | * This software was released into the Public Domain. As with most public |
---|
| 7 | * domain software, no warranty is made or implied by Crack dot Com, by |
---|
| 8 | * Jonathan Clark, or by Sam Hocevar. |
---|
| 9 | */ |
---|
[494] | 10 | |
---|
| 11 | #include <stdlib.h> |
---|
| 12 | #include <fcntl.h> |
---|
[555] | 13 | #if defined HAVE_SYS_IOCTL_H |
---|
| 14 | # include <sys/ioctl.h> |
---|
| 15 | # include <sys/stat.h> |
---|
| 16 | # include <sys/types.h> |
---|
[494] | 17 | #include <signal.h> |
---|
[555] | 18 | #endif |
---|
[494] | 19 | #include <sys/types.h> |
---|
| 20 | |
---|
[555] | 21 | #if defined __APPLE__ && !defined __MACH__ |
---|
| 22 | # include "GUSI.h" |
---|
| 23 | #elif defined HAVE_NETINET_IN_H |
---|
| 24 | # include <netdb.h> |
---|
| 25 | # include <netinet/in.h> |
---|
| 26 | # include <stdio.h> |
---|
| 27 | # include <string.h> |
---|
| 28 | # include <sys/time.h> |
---|
| 29 | # include <sys/ipc.h> |
---|
| 30 | # include <sys/shm.h> |
---|
| 31 | # include <sys/socket.h> |
---|
| 32 | # include <unistd.h> |
---|
| 33 | # ifdef HAVE_BSTRING_H |
---|
| 34 | # include <bstring.h> |
---|
| 35 | # else |
---|
| 36 | # include <sys/select.h> |
---|
| 37 | # endif |
---|
[494] | 38 | #endif |
---|
| 39 | |
---|
[555] | 40 | #include "sock.h" |
---|
| 41 | #include "isllist.h" |
---|
[494] | 42 | |
---|
[555] | 43 | extern fd_set master_set, master_write_set, read_set, exception_set, write_set; |
---|
| 44 | |
---|
[494] | 45 | class ip_address : public net_address |
---|
| 46 | { |
---|
| 47 | public: |
---|
| 48 | sockaddr_in addr; |
---|
| 49 | |
---|
| 50 | virtual protocol protocol_type() const { return net_address::IP; } |
---|
| 51 | virtual int equal(const net_address *who) const |
---|
| 52 | //{ {{ |
---|
| 53 | { |
---|
| 54 | if (who->protocol_type()==IP && |
---|
| 55 | !memcmp(&addr.sin_addr,& ((ip_address const *)who)->addr.sin_addr,sizeof(addr.sin_addr))) |
---|
| 56 | return 1; |
---|
| 57 | else return 0; |
---|
| 58 | } |
---|
| 59 | //}}} |
---|
| 60 | virtual int set_port(int port) { addr.sin_port=htons(port); return 1; } |
---|
| 61 | ip_address(sockaddr_in *Addr) { memcpy(&addr,Addr,sizeof(addr)); } |
---|
| 62 | virtual void print() |
---|
| 63 | //{ {{ |
---|
| 64 | { |
---|
| 65 | unsigned char *c=(unsigned char *) (&addr.sin_addr.s_addr); |
---|
| 66 | fprintf(stderr,"%d.%d.%d.%d",c[0],c[1],c[2],c[3]); |
---|
| 67 | } |
---|
| 68 | //}}} |
---|
| 69 | int get_port() { return htons(addr.sin_port); } |
---|
| 70 | net_address *copy() { return new ip_address(&addr); } |
---|
| 71 | ip_address() { } ; |
---|
| 72 | void store_string(char *st, int st_length) |
---|
| 73 | //{ {{ |
---|
| 74 | { |
---|
| 75 | char buf[100]; |
---|
| 76 | unsigned char *c=(unsigned char *) (&addr.sin_addr.s_addr); |
---|
| 77 | sprintf(buf,"%d.%d.%d.%d:%d",c[0],c[1],c[2],c[3],htons(addr.sin_port)); |
---|
| 78 | strncpy(st,buf,st_length); |
---|
| 79 | st[st_length-1]=0; |
---|
| 80 | } |
---|
| 81 | //}}} |
---|
| 82 | } ; |
---|
| 83 | |
---|
| 84 | class tcpip_protocol : public net_protocol |
---|
| 85 | { |
---|
| 86 | protected: |
---|
| 87 | // Request Data |
---|
| 88 | struct RequestItem |
---|
| 89 | { |
---|
| 90 | ip_address *addr; |
---|
| 91 | char name[256]; //name |
---|
| 92 | }; |
---|
| 93 | typedef isllist<RequestItem *>::iterator p_request; |
---|
| 94 | isllist<RequestItem*> servers,returned; |
---|
| 95 | |
---|
| 96 | // Notification Data |
---|
| 97 | net_socket *notifier; |
---|
| 98 | char notify_data[512]; |
---|
| 99 | int notify_len; |
---|
| 100 | |
---|
| 101 | net_socket *responder; |
---|
| 102 | ip_address *bcast; |
---|
| 103 | |
---|
| 104 | int handle_notification(); |
---|
| 105 | int handle_responder(); |
---|
| 106 | public : |
---|
| 107 | fd_set master_set,master_write_set,read_set,exception_set,write_set; |
---|
| 108 | |
---|
| 109 | tcpip_protocol(); |
---|
| 110 | net_address *get_local_address(); |
---|
| 111 | net_address *get_node_address(char const *&server_name, int def_port, int force_port); |
---|
| 112 | net_socket *connect_to_server(net_address *addr, |
---|
| 113 | net_socket::socket_type sock_type=net_socket::SOCKET_SECURE); |
---|
| 114 | net_socket *create_listen_socket(int port, net_socket::socket_type sock_type); |
---|
| 115 | int installed() { return 1; } // always part of unix |
---|
| 116 | char const *name() { return "UNIX generic TCPIP"; } |
---|
| 117 | void cleanup(); |
---|
| 118 | int select(int block); // return # of sockets available for read & writing |
---|
| 119 | |
---|
| 120 | // Notification methods |
---|
| 121 | virtual net_socket *start_notify(int port, void *data, int len); |
---|
| 122 | virtual void end_notify(); |
---|
| 123 | |
---|
| 124 | // Find notifiers methods |
---|
| 125 | virtual net_address *find_address(int port, char *name); // name should be a 256 byte buffer |
---|
| 126 | virtual void reset_find_list(); |
---|
| 127 | virtual ~tcpip_protocol() { cleanup(); } |
---|
| 128 | } ; |
---|
| 129 | |
---|
| 130 | extern tcpip_protocol tcpip; |
---|
| 131 | |
---|
| 132 | class unix_fd : public net_socket |
---|
| 133 | { |
---|
| 134 | protected : |
---|
| 135 | int fd; |
---|
| 136 | public : |
---|
| 137 | unix_fd(int fd) : fd(fd) { }; |
---|
| 138 | virtual int error() { return FD_ISSET(fd,&tcpip.exception_set); } |
---|
| 139 | virtual int ready_to_read() { return FD_ISSET(fd,&tcpip.read_set); } |
---|
| 140 | virtual int ready_to_write() |
---|
| 141 | { |
---|
| 142 | struct timeval tv={ 0,0}; // don't wait |
---|
| 143 | fd_set write_check; |
---|
| 144 | FD_ZERO(&write_check); |
---|
| 145 | FD_SET(fd,&write_check); |
---|
| 146 | select(FD_SETSIZE,NULL,&write_check,NULL,&tv); |
---|
| 147 | return FD_ISSET(fd,&write_check); |
---|
| 148 | } |
---|
| 149 | virtual int write(void const *buf, int size, net_address *addr=NULL); |
---|
| 150 | virtual int read(void *buf, int size, net_address **addr); |
---|
| 151 | |
---|
| 152 | virtual ~unix_fd() { read_unselectable(); write_unselectable(); close(fd); } |
---|
| 153 | virtual void read_selectable() { FD_SET(fd,&tcpip.master_set); } |
---|
| 154 | virtual void read_unselectable() { FD_CLR(fd,&tcpip.master_set); } |
---|
| 155 | virtual void write_selectable() { FD_SET(fd,&tcpip.master_write_set); } |
---|
| 156 | virtual void write_unselectable() { FD_CLR(fd,&tcpip.master_write_set); } |
---|
| 157 | int get_fd() { return fd; } |
---|
| 158 | |
---|
| 159 | void broadcastable(); |
---|
| 160 | } ; |
---|
| 161 | |
---|
| 162 | class tcp_socket : public unix_fd |
---|
| 163 | { |
---|
| 164 | int listening; |
---|
| 165 | public : |
---|
| 166 | tcp_socket(int fd) : unix_fd(fd) { listening=0; }; |
---|
| 167 | virtual int listen(int port) |
---|
| 168 | { |
---|
| 169 | sockaddr_in host; |
---|
| 170 | memset( (char*) &host,0, sizeof(host)); |
---|
| 171 | host.sin_family = AF_INET; |
---|
| 172 | host.sin_port = htons(port); |
---|
| 173 | host.sin_addr.s_addr = htonl(INADDR_ANY); |
---|
| 174 | if (bind(fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1) |
---|
| 175 | { |
---|
| 176 | fprintf(stderr,"net driver : could not bind socket to port %d\n",port); |
---|
| 177 | return 0; |
---|
| 178 | } |
---|
| 179 | if (::listen(fd,5)==-1) |
---|
| 180 | { |
---|
| 181 | fprintf(stderr,"net driver : could not listen to socket on port %d\n",port); |
---|
| 182 | return 0; |
---|
| 183 | } |
---|
| 184 | listening=1; |
---|
| 185 | return 1; |
---|
| 186 | } |
---|
| 187 | virtual net_socket *accept(net_address *&addr) |
---|
| 188 | { |
---|
| 189 | if (listening) |
---|
| 190 | { |
---|
| 191 | struct sockaddr_in from; |
---|
| 192 | socklen_t addr_len=sizeof(from); |
---|
| 193 | int new_fd=::accept(fd,(sockaddr *)&from,&addr_len); |
---|
| 194 | if (new_fd>=0) |
---|
| 195 | { |
---|
| 196 | addr=new ip_address(&from); |
---|
| 197 | return new tcp_socket(new_fd); |
---|
| 198 | } |
---|
| 199 | else |
---|
| 200 | { addr=NULL; return 0; } |
---|
| 201 | } |
---|
| 202 | return 0; |
---|
| 203 | } |
---|
| 204 | } ; |
---|
| 205 | |
---|
| 206 | class udp_socket : public unix_fd |
---|
| 207 | { |
---|
| 208 | public : |
---|
| 209 | udp_socket(int fd) : unix_fd(fd) { }; |
---|
| 210 | virtual int read(void *buf, int size, net_address **addr) |
---|
| 211 | { |
---|
| 212 | int tr; |
---|
| 213 | if (addr) |
---|
| 214 | { |
---|
| 215 | *addr=new ip_address; |
---|
| 216 | socklen_t addr_size=sizeof(sockaddr_in); |
---|
| 217 | tr=recvfrom(fd,buf,size,0, (sockaddr *) &((ip_address *)(*addr))->addr,&addr_size); |
---|
| 218 | } else |
---|
| 219 | tr=recv(fd,buf,size,0); |
---|
| 220 | return tr; |
---|
| 221 | } |
---|
| 222 | virtual int write(void const *buf, int size, net_address *addr=NULL) |
---|
| 223 | { |
---|
| 224 | if (addr) |
---|
| 225 | return sendto(fd,buf,size,0,(sockaddr *)(&((ip_address *)addr)->addr),sizeof(((ip_address *)addr)->addr)); |
---|
| 226 | else |
---|
| 227 | return ::write(fd,(char*)buf,size); |
---|
| 228 | } |
---|
| 229 | virtual int listen(int port) |
---|
| 230 | { |
---|
| 231 | sockaddr_in host; |
---|
| 232 | memset( (char*) &host,0, sizeof(host)); |
---|
| 233 | host.sin_family = AF_INET; |
---|
| 234 | host.sin_port = htons(port); |
---|
| 235 | host.sin_addr.s_addr = htonl(INADDR_ANY); |
---|
| 236 | if (bind(fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1) |
---|
| 237 | { |
---|
| 238 | fprintf(stderr,"net driver : could not bind socket to port %d\n",port); |
---|
| 239 | return 0; |
---|
| 240 | } |
---|
| 241 | return 1; |
---|
| 242 | } |
---|
| 243 | |
---|
| 244 | } ; |
---|
| 245 | |
---|