update
[btb/d2x.git] / arch / win32 / arch_ip.cpp
1 /*
2  * $Source: /cvs/cvsroot/d2x/arch/win32/arch_ip.cpp,v $
3  * $Revision: 1.2 $
4  * $Author: bradleyb $
5  * $Date: 2002-02-15 06:41:41 $
6  *
7  * arch_ip.cpp - arch specific udp/ip code.  (win32 ver)
8  * added 2000/02/07 Matt Mueller (some code borrowed from ipx_udp.c)
9  *
10  * $Log: not supported by cvs2svn $
11  * Revision 1.1  2002/02/15 02:29:33  bradleyb
12  * copied from d1x
13  *
14  *
15  */
16
17 #ifdef HAVE_CONFIG_H
18 #include <conf.h>
19 #endif
20
21 #include <string.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25 extern "C" {
26 #include "ipx_drv.h"
27 #include "pstypes.h"
28 #include "mono.h"
29 //#include "multi.h"
30 }
31
32 #include "ip_base.h"
33 #include "ipclient.h"
34
35 //static int dynamic_socket=0x402;
36
37 static int mysock=-1;
38
39 //static unsigned char qhbuf[6];
40
41
42 /* Do hostname resolve on name "buf" and return the address in buffer "qhbuf".
43  */
44 int arch_ip_queryhost(ip_addr *addr,char *buf,u_short baseport)
45 {
46         struct hostent *he;
47         char *s;
48         char c=0;
49         u_short p;
50
51         if ((s=strrchr(buf,':'))) {
52                 c=*s;
53                 *s='\0';
54                 p=ip_portshift(baseport,s+1);
55         }
56         else p=ip_portshift(baseport,NULL);//memset(qhbuf+4,0,2);
57         he=gethostbyname((char *)buf);
58         if (s) *s=c;
59         if (!he) {
60                 msg("Error resolving my hostname \"%s\"",buf);
61                 return -1; //(NULL);
62         }
63         if (he->h_addrtype!=AF_INET || he->h_length!=4) {
64                 msg("Error parsing resolved my hostname \"%s\"",buf);
65                 return -1;//(NULL);
66         }
67         if (!*he->h_addr_list) {
68                 msg("My resolved hostname \"%s\" address list empty",buf);
69                 return -1;//(NULL);
70         }
71         addr->set(4,(u_char*)*he->h_addr_list,p);
72 //      memcpy(qhbuf,(*he->h_addr_list),4);
73 //      return(qhbuf);
74         return 0;
75 }
76
77 #ifdef UDPDEBUG
78 /* Like dumpraddr() but for structure "sockaddr_in"
79  */
80
81 static void dumpaddr(struct sockaddr_in *sin)
82 {
83         unsigned short ports;
84         u_char qhbuf[6];
85
86         memcpy(qhbuf+0,&sin->sin_addr,4);
87         //ports=htons(((short)ntohs(sin->sin_port))-UDP_BASEPORT);
88         ports=sin->sin_port;
89         memcpy(qhbuf+4,&ports,2);
90         dumpraddr(qhbuf);
91 }
92 #endif
93
94
95 int ip_sendtoca(ip_addr addr,const void *buf,int len){
96         struct sockaddr_in toaddr;
97         if (addr.addrlen()!=4) return 0;//not handled yet
98         toaddr.sin_family=AF_INET;
99         memcpy(&toaddr.sin_addr,addr.addr,4);
100         toaddr.sin_port=*(unsigned short *)(addr.addr+4);
101 #ifdef UDPDEBUG
102         con_printf(CON_DEBUG, MSGHDR "sendtoca((%d) ",len);
103         //dumpraddr(addr.addr);
104         addr.dump();
105         con_printf(").\n");
106 #endif
107         return sendto(mysock,(char*)buf,len,0,(struct sockaddr *)&toaddr,sizeof(toaddr));
108 }
109
110
111 int arch_ip_get_my_addr(u_short myport){
112         char buf[256];
113         if (gethostname(buf,sizeof(buf))) FAIL("Error getting my hostname");
114
115         ip_addr ip;
116         if (ip.dns(buf,myport)) FAIL("Error querying my own hostname \"%s\"",buf);
117         ip_my_addrs.add(ip);
118         return 0;
119 }
120 int arch_ip_open_socket(int port){
121         struct sockaddr_in sin;
122         int val_one=1;
123         WORD wVersionRequested;
124         WSADATA wsaData;
125
126         wVersionRequested = MAKEWORD(2, 0);
127         if (WSAStartup( wVersionRequested, &wsaData))
128         {
129                 return -1;
130         }
131 #if 0
132         if ( LOBYTE( wsaData.wVersion ) != 2 ||
133                         HIBYTE( wsaData.wVersion ) != 0 ) {
134                 /* We couldn't find a usable WinSock DLL. */
135                 WSACleanup( );
136                 return -2;
137         }
138 #endif
139
140         if ((mysock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) {
141                 mysock = -1;
142                 FAIL("socket() creation failed on port %d: %m",port);
143         }
144         if (setsockopt(mysock,SOL_SOCKET,SO_BROADCAST,(char*)&val_one,sizeof(val_one))) {
145                 if (close(mysock)) msg("close() failed during error recovery: %m");
146                 mysock=-1;
147                 FAIL("setsockopt(SO_BROADCAST) failed: %m");
148         }
149         sin.sin_family=AF_INET;
150         sin.sin_addr.s_addr=htonl(INADDR_ANY);
151         sin.sin_port=htons(port);
152
153         if (bind(mysock,(struct sockaddr *)&sin,sizeof(sin))) {
154                 if (close(mysock)) msg("close() failed during error recovery: %m");
155                 mysock=-1;
156                 FAIL("bind() to UDP port %d failed: %m",port);
157         }
158
159         return 0;
160 }
161 void arch_ip_close_socket(void) {
162         if (mysock<0) {
163                 msg("close w/o open");
164                 return;
165         }
166         if (closesocket(mysock))
167                 msg("close() failed on CloseSocket D1X ip socket %m");
168         mysock=-1;
169         WSACleanup();
170 }
171 int arch_ip_recvfrom(char*outbuf,int outbufsize,struct ipx_recv_data *rd){
172         struct sockaddr_in fromaddr;
173         int fromaddrsize=sizeof(fromaddr);
174         int size;
175         static ip_addr ip_fromaddr;
176         ip_addr *vptr=&ip_fromaddr;
177
178         if ((size=recvfrom(mysock,outbuf,outbufsize,0,(struct sockaddr *)&fromaddr,&fromaddrsize))<0)
179                 return -1;
180
181         if (fromaddr.sin_family!=AF_INET) return -1;
182
183 #ifdef UDPDEBUG
184         con_printf(CON_DEBUG, MSGHDR "recvfrom((%d-2=%d),",size,size-2);
185         dumpaddr(&fromaddr);
186         con_printf(CON_DEBUG(").\n");
187 #endif
188
189         ip_fromaddr.set(4,(u_char*)&fromaddr.sin_addr,fromaddr.sin_port);
190
191         memcpy(rd->src_node,&vptr,sizeof(ip_addr*));
192         return size;
193 }
194 int arch_ip_PacketReady(void) {
195         return ipx_general_PacketReady(mysock);
196 }