2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
15 * $Source: /cvs/cvsroot/d2x/main/ipx_drv.c,v $
18 * $Date: 2001-10-19 04:10:27 $
20 * FIXME: put description here
22 * $Log: not supported by cvs2svn $
33 #include <sys/types.h>
46 //added 05/17/99 Matt Mueller - needed to redefine FD_* so that no asm is used
49 #define MAX_IPX_DATA 576
51 ubyte broadcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
52 ubyte null_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
55 //ipx_socket_t ipx_socket_data;
56 ubyte ipx_installed=0;
57 ubyte ipx_atexit_installed=0;
58 //ushort ipx_socket = 0;
59 u_int32_t ipx_network = 0;
60 ubyte ipx_MyAddress[10];
61 int ipx_packetnum = 0; /* Sequence number */
63 /* User defined routing stuff */
64 typedef struct user_address {
70 int Ipx_num_users = 0;
71 user_address Ipx_users[MAX_USERS];
73 #define MAX_NETWORKS 64
74 int Ipx_num_networks = 0;
75 uint Ipx_networks[MAX_NETWORKS];
79 int ipx_general_PacketReady(int fd) {
85 tv.tv_sec = tv.tv_usec = 0;
86 if (select(fd + 1, &set, NULL, NULL, &tv) > 0)
92 struct ipx_driver *driver = NULL;
94 ubyte * ipx_get_my_server_address()
96 return (ubyte *)&ipx_network;
99 ubyte * ipx_get_my_local_address()
101 return (ubyte *)(ipx_MyAddress + 4);
104 //---------------------------------------------------------------
105 // Initializes all IPX internals.
106 // If socket_number==0, then opens next available socket.
107 // Returns: 0 if successful.
108 // -1 if socket already open.
109 // -2 if socket table full.
110 // -3 if IPX not installed.
111 // -4 if couldn't allocate low dos memory
112 // -5 if error with getting internetwork address
113 int ipx_init( int socket_number )
116 if (!driver) return -1;
117 memset(ipx_MyAddress,0,10);
118 if ((i = FindArg("-ipxnetwork")) && Args[i + 1]) {
119 unsigned long n = strtol(Args[i + 1], NULL, 16);
120 ipx_MyAddress[0] = n >> 24; ipx_MyAddress[1] = (n >> 16) & 255;
121 ipx_MyAddress[2] = (n >> 8) & 255; ipx_MyAddress[3] = n & 255;
122 printf("IPX: Using network %08x\n", (unsigned int)n);
124 if (driver->OpenSocket(socket_number)) {
128 // if (driver->GetMyAddress)
129 // driver->GetMyAddress();
130 memcpy(&ipx_network, ipx_MyAddress, 4);
131 Ipx_num_networks = 0;
132 memcpy( &Ipx_networks[Ipx_num_networks++], &ipx_network, 4 );
134 if (ipx_atexit_installed==0){
136 ipx_atexit_installed=1;
144 driver->CloseSocket();
149 int ipx_set_driver(char *arg)
153 if (!FindArg( "-nonetwork" )) {
157 if (Inferno_verbose) printf( "\n%s ", TXT_INITIALIZING_NETWORK);
158 if ((t=FindArg("-socket")))
159 socket = atoi( Args[t+1] );
161 if ((t=FindArg("-pps")) && (t = atoi(Args[t+1])) && (t >= 2) && (t <= 20)) {
162 Network_initial_pps = t;
164 if ( FindArg("-shortpackets") )
165 Network_initial_shortpackets = 1;
167 #ifdef SUPPORTS_NET_IP
168 if (strcmp(arg,"ip")==0){
172 driver=arch_ipx_set_driver(arg);
173 if ((ipx_error=ipx_init(IPX_DEFAULT_SOCKET+socket))==0) {
174 if (Inferno_verbose) printf( "%s %d.\n", TXT_IPX_CHANNEL, socket );
177 switch( ipx_error ) {
178 case 3: if (Inferno_verbose) printf( "%s\n", TXT_NO_NETWORK); break;
179 case -2: if (Inferno_verbose) printf( "%s 0x%x.\n", TXT_SOCKET_ERROR, IPX_DEFAULT_SOCKET+socket); break;
180 case -4: if (Inferno_verbose) printf( "%s\n", TXT_MEMORY_IPX ); break;
182 if (Inferno_verbose) printf( "%s %d", TXT_ERROR_IPX, ipx_error );
184 if (Inferno_verbose) printf( "%s\n",TXT_NETWORK_DISABLED);
185 Network_active = 0; // Assume no network
187 ipx_read_user_file( "descent.usr" );
188 ipx_read_network_file( "descent.net" );
189 //if ( FindArg( "-dynamicsockets" ))
190 // Network_allow_socket_changes = 1;
192 // Network_allow_socket_changes = 0;
194 if (Inferno_verbose) printf( "%s\n", TXT_NETWORK_DISABLED);
195 Network_active = 0; // Assume no network
198 return ipx_installed?0:-1;
201 int ipx_get_packet_data( ubyte * data )
203 if (driver->GetPacketData)
204 return driver->GetPacketData(data);
206 struct ipx_recv_data rd;
209 if (driver->usepacketnum)
210 buf=alloca(MAX_IPX_DATA);
213 //edited 04/12/99 Matt Mueller - duh, we don't want to throw all that data away!
214 while (driver->PacketReady()) {
215 if ((size = driver->ReceivePacket(buf, MAX_IPX_DATA, &rd)) > 4) {
216 if (!memcmp(rd.src_network, ipx_MyAddress, 10)) {
217 mprintf((0,"dumped my own packet\n"));
218 continue; /* don't get own pkts */
220 if (driver->usepacketnum){
221 memcpy(data, buf + 4, size - 4);
232 void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address )
234 if (driver->SendPacketData)
235 driver->SendPacketData(data,datasize,network,address,immediate_address);
237 IPXPacket_t ipx_header;
239 memcpy(ipx_header.Destination.Network, network, 4);
240 memcpy(ipx_header.Destination.Node, immediate_address, 6);
241 // *(ushort *)ipx_header.Destination.Socket = htons(ipx_socket_data.socket);
242 ipx_header.PacketType = 4; /* Packet Exchange */
244 if (driver->usepacketnum){
245 ubyte buf[MAX_IPX_DATA];
246 *(uint *)buf = ipx_packetnum++;
248 memcpy(buf + 4, data, datasize);
249 driver->SendPacket(&ipx_header, buf, datasize + 4);
251 driver->SendPacket(&ipx_header, data, datasize);//we can save 4 bytes
255 void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target )
257 if (driver->GetLocalTarget)
258 driver->GetLocalTarget(server,node,local_target);
260 // let's hope Linux knows how to route it
261 memcpy( local_target, node, 6 );
264 void ipx_send_broadcast_packet_data( ubyte * data, int datasize )
267 ubyte local_address[6];
269 // Set to all networks besides mine
270 for (i=0; i<Ipx_num_networks; i++ ) {
271 if ( memcmp( &Ipx_networks[i], &ipx_network, 4 ) ) {
272 ipx_get_local_target( (ubyte *)&Ipx_networks[i], broadcast_addr, local_address );
273 ipx_send_packet_data( data, datasize, (ubyte *)&Ipx_networks[i], broadcast_addr, local_address );
275 ipx_send_packet_data( data, datasize, (ubyte *)&Ipx_networks[i], broadcast_addr, broadcast_addr );
279 //OLDipx_send_packet_data( data, datasize, (ubyte *)&ipx_network, broadcast_addr, broadcast_addr );
281 // Send directly to all users not on my network or in the network list.
282 for (i=0; i<Ipx_num_users; i++ ) {
283 if ( memcmp( Ipx_users[i].network, &ipx_network, 4 ) ) {
284 for (j=0; j<Ipx_num_networks; j++ ) {
285 if (!memcmp( Ipx_users[i].network, &Ipx_networks[j], 4 ))
288 ipx_send_packet_data( data, datasize, Ipx_users[i].network, Ipx_users[i].node, Ipx_users[i].address );
295 // Sends a non-localized packet... needs 4 byte server, 6 byte address
296 void ipx_send_internetwork_packet_data( ubyte * data, int datasize, ubyte * server, ubyte *address )
298 ubyte local_address[6];
300 if ( (*(uint *)server) != 0 ) {
301 ipx_get_local_target( server, address, local_address );
302 ipx_send_packet_data( data, datasize, server, address, local_address );
304 // Old method, no server info.
305 ipx_send_packet_data( data, datasize, server, address, address );
309 int ipx_check_ready_to_join(ubyte *server, ubyte *node){
310 if (!driver->CheckReadyToJoin)
312 return driver->CheckReadyToJoin(server,node);
316 int ipx_change_default_socket( ushort socket_number )
318 if ( !ipx_installed ) return -3;
320 driver->CloseSocket();
321 if (driver->OpenSocket(socket_number)) {
327 void ipx_read_user_file(char * filename)
331 char temp_line[132], *p1;
334 if (!filename) return;
338 fp = fopen( filename, "rt" );
341 printf( "Broadcast Users:\n" );
343 while (fgets(temp_line, 132, fp)) {
345 p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0';
346 p1 = strchr(temp_line,';'); if (p1) *p1 = '\0';
347 #if 1 // adb: replaced sscanf(..., "%2x...", (char *)...) with better, but longer code
348 if (strlen(temp_line) >= 21 && temp_line[8] == '/') {
349 for (n = 0; n < 4; n++) {
350 if (sscanf(temp_line + n * 2, "%2x", &x) != 1)
356 for (n = 0; n < 6; n++) {
357 if (sscanf(temp_line + 9 + n * 2, "%2x", &x) != 1)
366 n = sscanf( temp_line, "%2x%2x%2x%2x/%2x%2x%2x%2x%2x%2x", &tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3], &tmp.node[0], &tmp.node[1], &tmp.node[2],&tmp.node[3], &tmp.node[4], &tmp.node[5] );
367 if ( n != 10 ) continue;
369 if ( Ipx_num_users < MAX_USERS ) {
370 ubyte * ipx_real_buffer = (ubyte *)&tmp;
371 ipx_get_local_target( tmp.network, tmp.node, tmp.address );
372 Ipx_users[Ipx_num_users++] = tmp;
373 printf( "%02X%02X%02X%02X/", ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3] );
374 printf( "%02X%02X%02X%02X%02X%02X\n", ipx_real_buffer[4],ipx_real_buffer[5],ipx_real_buffer[6],ipx_real_buffer[7],ipx_real_buffer[8],ipx_real_buffer[9] );
376 printf( "Too many addresses in %s! (Limit of %d)\n", filename, MAX_USERS );
385 void ipx_read_network_file(char * filename)
389 char temp_line[132], *p1;
392 if (!filename) return;
394 fp = fopen( filename, "rt" );
397 printf( "Using Networks:\n" );
398 for (i=0; i<Ipx_num_networks; i++ ) {
399 ubyte * n1 = (ubyte *)&Ipx_networks[i];
400 printf("* %02x%02x%02x%02x\n", n1[0], n1[1], n1[2], n1[3] );
403 while (fgets(temp_line, 132, fp)) {
405 p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0';
406 p1 = strchr(temp_line,';'); if (p1) *p1 = '\0';
407 #if 1 // adb: replaced sscanf(..., "%2x...", (char *)...) with better, but longer code
408 if (strlen(temp_line) >= 8) {
409 for (n = 0; n < 4; n++) {
410 if (sscanf(temp_line + n * 2, "%2x", &x) != 1)
419 n = sscanf( temp_line, "%2x%2x%2x%2x", &tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3] );
420 if ( n != 4 ) continue;
422 if ( Ipx_num_networks < MAX_NETWORKS ) {
424 for (j=0; j<Ipx_num_networks; j++ )
425 if ( !memcmp( &Ipx_networks[j], tmp.network, 4 ) )
427 if ( j >= Ipx_num_networks ) {
428 memcpy( &Ipx_networks[Ipx_num_networks++], tmp.network, 4 );
429 printf(" %02x%02x%02x%02x\n", tmp.network[0], tmp.network[1], tmp.network[2], tmp.network[3] );
432 printf( "Too many networks in %s! (Limit of %d)\n", filename, MAX_NETWORKS );