Moved win32_* to win32/* (a la d1x), starting to get net working.
[btb/d2x.git] / arch / win32 / ipx_win.c
1 /*
2  * $Source: /cvs/cvsroot/d2x/arch/win32/ipx_win.c,v $
3  * $Revision: 1.2 $
4  * $Author: bradleyb $
5  * $Date: 2001-10-19 00:23:56 $
6  *
7  * IPX driver using BSD style sockets
8  * Mostly taken from dosemu
9  *
10  * $Log: not supported by cvs2svn $
11  * Revision 1.3  2001/01/29 13:35:09  bradleyb
12  * Fixed build system, minor fixes
13  *
14  */
15
16 #ifdef HAVE_CONFIG_H
17 #include <conf.h>
18 #endif
19
20 #include <string.h>
21 #include <stdlib.h>
22 #include <winsock.h>
23 //#include <errno.h>
24
25 #include "ipx_drv.h"
26 #include "wsipx.h"
27
28 #include "mono.h"
29
30 static ipx_socket_t mysock;
31
32 //#define n_printf(format, args...) mprintf((1, format, ## args))
33
34 static int ipx_win_GetMyAddress( void )
35 {
36 #if 0
37   int sock;
38   struct sockaddr_ipx ipxs;
39   struct sockaddr_ipx ipxs2;
40   int len;
41   int i;
42   
43 //  sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
44   sock=socket(AF_IPX,SOCK_DGRAM,0);
45
46   if(sock==-1)
47   {
48     mprintf((1,"IPX: could not open socket in GetMyAddress\n"));
49     return(-1);
50   }
51
52   /* bind this socket to network 0 */  
53   ipxs.sa_family=AF_IPX;
54 #ifdef IPX_MANUAL_ADDRESS
55   memcpy(ipxs.sa_netnum, ipx_MyAddress, 4);
56 #else
57   memset(ipxs.sa_netnum, 0, 4);
58 #endif  
59   ipxs.sa_socket=0;
60   
61   if(bind(sock,(struct sockaddr *)&ipxs,sizeof(ipxs))==-1)
62   {
63     mprintf((1,"IPX: could bind to network 0 in GetMyAddress\n"));
64     closesocket( sock );
65     return(-1);
66   }
67   
68   len = sizeof(ipxs2);
69   if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
70     mprintf((1,"IPX: could not get socket name in GetMyAddress\n"));
71     closesocket( sock );
72     return(-1);
73   }
74
75   memcpy(ipx_MyAddress, ipxs2.sa_netnum, 4);
76   for (i = 0; i < 6; i++) {
77     ipx_MyAddress[4+i] = ipxs2.sa_nodenum[i];
78   }
79 /*  printf("My address is 0x%.4X:%.2X.%.2X.%.2X.%.2X.%.2X.%.2X\n", *((int *)ipxs2.sa_netnum), ipxs2.sa_nodenum[0],
80   ipxs2.sa_nodenum[1], ipxs2.sa_nodenum[2], ipxs2.sa_nodenum[3], ipxs2.sa_nodenum[4], ipxs2.sa_nodenum[5]);*/
81
82     closesocket( sock );
83
84 #endif
85   return(0);
86 }
87
88 static int ipx_win_OpenSocket(int port)
89 {
90   int sock;                     /* sock here means Linux socket handle */
91   int opt;
92   struct sockaddr_ipx ipxs;
93   int len;
94   struct sockaddr_ipx ipxs2;
95
96         WORD wVersionRequested;
97         WSADATA wsaData;
98
99         wVersionRequested = MAKEWORD(2, 0);
100         if (WSAStartup( wVersionRequested, &wsaData))
101         {
102           return -1;
103         }
104 #if 0
105         if ( LOBYTE( wsaData.wVersion ) != 2 ||
106           HIBYTE( wsaData.wVersion ) != 0 ) {
107            /* We couldn't find a usable WinSock DLL. */
108            WSACleanup( );
109            return -2;
110         }
111 #endif
112
113
114   /* DANG_FIXTHIS - kludge to support broken linux IPX stack */
115   /* need to convert dynamic socket open into a real socket number */
116 /*  if (port == 0) {
117     mprintf((1,"IPX: using socket %x\n", nextDynamicSocket));
118     port = nextDynamicSocket++;
119   }
120 */
121   /* do a socket call, then bind to this port */
122 //  sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
123 //  sock = socket(AF_IPX, SOCK_DGRAM, 0);
124   sock = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);//why NSPROTO_IPX?  I looked in the quake source and thats what they used. :) -MPM  (on w2k 0 and PF_IPX don't work)
125   if (sock == -1) {
126     mprintf((1,"IPX: could not open IPX socket.\n"));
127     return -1;
128   }
129
130
131   opt = 1;
132   /* Permit broadcast output */
133   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
134                  (const char *)&opt, sizeof(opt)) == -1) {
135     mprintf((1,"IPX: could not set socket option for broadcast.\n"));
136     return -1;
137   }
138   ipxs.sa_family = AF_IPX;
139   memcpy(ipxs.sa_netnum, ipx_MyAddress, 4);
140 //  *((unsigned int *)&ipxs.sa_netnum[0]) = *((unsigned int *)&ipx_MyAddress[0]);
141 /*  ipxs.sa_netnum = htonl(MyNetwork); */
142   memset(ipxs.sa_nodenum, 0, 6);
143 //  bzero(ipxs.sa_nodenum, 6);  /* Please fill in my node name */
144   ipxs.sa_socket = htons((short)port);
145
146   /* now bind to this port */
147   if (bind(sock, (struct sockaddr *) &ipxs, sizeof(ipxs)) == -1) {
148     mprintf((1,"IPX: could not bind socket to address\n"));
149     closesocket( sock );
150     return -1;
151   }
152   
153 //  if( port==0 ) {
154 //    len = sizeof(ipxs2);
155 //    if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
156 //       //n_printf("IPX: could not get socket name in IPXOpenSocket\n");
157 //     closesocket( sock );
158 //      return -1;
159 //    } else {
160 //      port = htons(ipxs2.sa_socket);
161 //      //n_printf("IPX: opened dynamic socket %04x\n", port);
162 //    }
163   len = sizeof(ipxs2);
164   if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
165     mprintf((1,"IPX: could not get socket name in IPXOpenSocket\n"));
166     closesocket( sock );
167     return -1;
168   } 
169   if (port == 0) {
170     port = htons(ipxs2.sa_socket);
171     mprintf((1,"IPX: opened dynamic socket %04x\n", port));
172   }
173
174   memcpy(ipx_MyAddress, ipxs2.sa_netnum, 4);
175   memcpy(ipx_MyAddress + 4, ipxs2.sa_nodenum, 6);
176
177   mysock.fd = sock;
178   mysock.socket = port;
179
180   ipx_win_GetMyAddress();
181
182   return 0;
183 }
184
185 static void ipx_win_CloseSocket(void) {
186   /* now close the file descriptor for the socket, and free it */
187   mprintf((1,"IPX: closing file descriptor on socket %x\n", mysock.socket));
188   closesocket(mysock.fd);
189   WSACleanup();
190 }
191
192 static int ipx_win_SendPacket(IPXPacket_t *IPXHeader,
193  ubyte *data, int dataLen) {
194   struct sockaddr_ipx ipxs;
195  
196   ipxs.sa_family = AF_IPX;
197   /* get destination address from IPX packet header */
198   memcpy(&ipxs.sa_netnum, IPXHeader->Destination.Network, 4);
199   /* if destination address is 0, then send to my net */
200   if ((*(unsigned int *)&ipxs.sa_netnum) == 0) {
201     (*(unsigned int *)&ipxs.sa_netnum)= *((unsigned int *)&ipx_MyAddress[0]);
202 /*  ipxs.sa_netnum = htonl(MyNetwork); */
203   }
204   memcpy(&ipxs.sa_nodenum, IPXHeader->Destination.Node, 6);
205 //  memcpy(&ipxs.sa_socket, IPXHeader->Destination.Socket, 2);
206   ipxs.sa_socket=htons(mysock.socket);
207 //  ipxs.sa_type = IPXHeader->PacketType;
208   /*    ipxs.sipx_port=htons(0x452); */
209   return sendto(mysock.fd, data, dataLen, 0,
210              (struct sockaddr *) &ipxs, sizeof(ipxs));
211 }
212
213 static int ipx_win_ReceivePacket(char *buffer, int bufsize, 
214  struct ipx_recv_data *rd) {
215         int sz, size;
216         struct sockaddr_ipx ipxs;
217  
218         sz = sizeof(ipxs);
219         if ((size = recvfrom(mysock.fd, buffer, bufsize, 0,
220              (struct sockaddr *) &ipxs, &sz)) <= 0)
221              return size;
222         memcpy(rd->src_network, ipxs.sa_netnum, 4);
223         memcpy(rd->src_node, ipxs.sa_nodenum, 6);
224         rd->src_socket = ipxs.sa_socket;
225         rd->dst_socket = mysock.socket;
226 //      rd->pkt_type = ipxs.sipx_type;
227   
228         return size;
229 }
230
231 static int ipx_win_general_PacketReady(void) {
232         return ipx_general_PacketReady(mysock.fd);
233 }
234
235 struct ipx_driver ipx_win = {
236 //      ipx_win_GetMyAddress,
237         ipx_win_OpenSocket,
238         ipx_win_CloseSocket,
239         ipx_win_SendPacket,
240         ipx_win_ReceivePacket,
241         ipx_win_general_PacketReady,
242         NULL,
243         1,
244         NULL,
245         NULL,
246         NULL
247 };