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