IPXMGR.CPP (85514B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /CounterStrike/IPXMGR.CPP 3 10/13/97 2:20p Steve_t $ */ 17 /*************************************************************************** 18 ** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ** 19 *************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : IPXMGR.CPP * 24 * * 25 * Programmer : Bill Randolph * 26 * * 27 * Start Date : December 20, 1994 * 28 * * 29 * Last Update : May 4, 1995 [BRR] * 30 * * 31 *-------------------------------------------------------------------------* 32 * Functions: * 33 * IPXManagerClass::IPXManagerClass -- class constructor * 34 * IPXManagerClass::~IPXManagerClass -- class destructor * 35 * IPXManagerClass::Init -- initialization routine * 36 * IPXManagerClass::Is_IPX -- tells if IPX is installed or not * 37 * IPXManagerClass::Set_Timing -- sets timing for all connections * 38 * IPXManagerClass::Create_Connection -- creates a new connection * 39 * IPXManagerClass::Delete_Connection -- deletes a connection * 40 * IPXManagerClass::Num_Connections -- gets the # of connections * 41 * IPXManagerClass::Connection_ID -- gets the given connection's ID * 42 * IPXManagerClass::Connection_Name -- gets name for given connection * 43 * IPXManagerClass::Connection_Address -- retrieves connection's address * 44 * IPXManagerClass::Connection_Index -- gets given connection's index * 45 * IPXManagerClass::Set_Connection_Parms -- sets connection's name & id * 46 * IPXManagerClass::Send_Global_Message -- sends a Global Message * 47 * IPXManagerClass::Get_Global_Message -- polls the Global Message queue * 48 * IPXManagerClass::Send_Private_Message -- Sends a Private Message * 49 * IPXManagerClass::Get_Private_Message -- Polls Private Message queue * 50 * IPXManagerClass::Service -- main polling routine for IPX Connections * 51 * IPXManagerClass::Get_Bad_Connection -- returns bad connection ID * 52 * IPXManagerClass::Global_Num_Send -- gets # entries in send queue * 53 * IPXManagerClass::Global_Num_Receive -- gets # entries in recv queue * 54 * IPXManagerClass::Private_Num_Send -- gets # entries in send queue * 55 * IPXManagerClass::Private_Num_Receive -- gets # entries in recv queue * 56 * IPXManagerClass::Set_Bridge -- prepares to cross a bridge * 57 * IPXManagerClass::Set_Socket -- sets socket ID for all connections * 58 * IPXManagerClass::Response_Time -- Returns largest Avg Response Time * 59 * IPXManagerClass::Global_Response_Time -- Returns Avg Response Time * 60 * IPXManagerClass::Reset_Response_Time -- Reset response time * 61 * IPXManagerClass::Oldest_Send -- gets ptr to oldest send buf * 62 * IPXManagerClass::Mono_Debug_Print -- debug output routine * 63 * IPXManagerClass::Alloc_RealMode_Mem -- allocates real-mode memory * 64 * IPXManagerClass::Free_RealMode_Mem -- frees real-mode memory * 65 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 66 67 #include "function.h" 68 #include <stdio.h> 69 //#include <mem.h> PG 70 //#include <i86.h> PG 71 #include "ipxmgr.h" 72 #include "wwlib32.h" // to enable mono output 73 74 #ifdef WINSOCK_IPX 75 76 #include "WSProto.h" 77 #include "WSPIPX.h" 78 79 #else //WINSOCK_IPX 80 81 #include "ipx95.h" 82 #ifdef WIN32 83 #include "tcpip.h" 84 #else 85 #include "fakesock.h" 86 #endif //WIN32 87 88 #endif //WINSOCK_IPX 89 90 // Turn off "expression is not meaningful". 91 //#pragma warning 628 9 92 93 //#include "WolDebug.h" 94 95 /*************************************************************************** 96 * IPXManagerClass::IPXManagerClass -- class constructor * 97 * * 98 * INPUT: * 99 * glb_maxlen Global Channel maximum packet length * 100 * pvt_maxlen Private Channel maximum packet length * 101 * socket socket ID to use * 102 * product_id a unique numerical ID for this product * 103 * * 104 * OUTPUT: * 105 * none. * 106 * * 107 * WARNINGS: * 108 * The socket number is byte-swapped, since IPX requires socket ID's * 109 * to be stored high/low. * 110 * * 111 * HISTORY: * 112 * 12/20/1994 BR : Created. * 113 *=========================================================================*/ 114 IPXManagerClass::IPXManagerClass (int glb_maxlen, int pvt_maxlen, 115 int glb_num_packets, int pvt_num_packets, unsigned short socket, 116 unsigned short product_id) 117 { 118 int i; 119 #ifdef WINSOCK_IPX 120 /* 121 ** Find out if Packet protocol services are available through Winsock. 122 */ 123 if ( PacketTransport ) { 124 delete PacketTransport; 125 PacketTransport = NULL; 126 } 127 PacketTransport = new WinsockInterfaceClass; 128 assert ( PacketTransport != NULL ); 129 130 if ( PacketTransport->Init() ){ 131 IPXStatus = 1; 132 }else{ 133 IPXStatus = 0; 134 } 135 delete PacketTransport; 136 PacketTransport = NULL; 137 138 #else //WINSOCK_IPX 139 140 //------------------------------------------------------------------------ 141 // Initialize data members 142 //------------------------------------------------------------------------ 143 //........................................................................ 144 // IPXStatus = 1 if IPX is installed, 0 if not 145 //........................................................................ 146 if (IPX_SPX_Installed()==0) { 147 IPXStatus = 0; 148 } 149 else { 150 IPXStatus = 1; 151 } 152 #endif //WINSOCK_IPX 153 154 //........................................................................ 155 // Set listening state flag to off 156 //........................................................................ 157 Listening = 0; 158 159 //........................................................................ 160 // No memory has been alloc'd yet 161 //........................................................................ 162 RealMemAllocd = 0; 163 164 //........................................................................ 165 // Set max packet sizes, for allocating real-mode memory 166 //........................................................................ 167 Glb_MaxPacketLen = glb_maxlen; 168 Glb_NumPackets = glb_num_packets; 169 Pvt_MaxPacketLen = pvt_maxlen; 170 Pvt_NumPackets = pvt_num_packets; 171 172 //........................................................................ 173 // Save the app's product ID 174 //........................................................................ 175 ProductID = product_id; 176 177 //........................................................................ 178 // Save our socket ID number 179 //........................................................................ 180 Socket = (unsigned short)( (((unsigned long)socket & 0x00ff) << 8) | 181 (((unsigned long)socket & 0xff00) >> 8)); 182 183 //------------------------------------------------------------------------ 184 // Get the user's IPX local connection number 185 //------------------------------------------------------------------------ 186 ConnectionNum = 0; 187 #ifndef WINSOCK_IPX 188 if (IPXStatus) { 189 ConnectionNum = IPX_Get_Connection_Number(); 190 } 191 #endif //WINSOCK_IPX 192 193 //------------------------------------------------------------------------ 194 // Init connection states 195 //------------------------------------------------------------------------ 196 NumConnections = 0; 197 CurConnection = 0; 198 for (i = 0; i < CONNECT_MAX; i++) { 199 Connection[i] = 0; 200 } 201 GlobalChannel = 0; 202 203 SendOverflows = 0; 204 ReceiveOverflows = 0; 205 BadConnection = CONNECTION_NONE; 206 207 //------------------------------------------------------------------------ 208 // Init timing parameters 209 //------------------------------------------------------------------------ 210 RetryDelta = 2; // 2 ticks between retries 211 MaxRetries = -1; // disregard # retries 212 Timeout = 60; // report bad connection after 1 second 213 214 } /* end of IPXManagerClass */ 215 216 217 /*************************************************************************** 218 * IPXManagerClass::~IPXManagerClass -- class destructor * 219 * * 220 * INPUT: * 221 * none. * 222 * * 223 * OUTPUT: * 224 * none. * 225 * * 226 * WARNINGS: * 227 * none. * 228 * * 229 * HISTORY: * 230 * 12/20/1994 BR : Created. * 231 *=========================================================================*/ 232 IPXManagerClass::~IPXManagerClass() 233 { 234 int i; 235 236 //------------------------------------------------------------------------ 237 // Stop all IPX events 238 //------------------------------------------------------------------------ 239 if (Listening) { 240 IPXConnClass::Stop_Listening(); 241 Listening = 0; 242 } 243 244 //------------------------------------------------------------------------ 245 // Free all protected-mode memory 246 //------------------------------------------------------------------------ 247 if (GlobalChannel) { 248 delete GlobalChannel; 249 GlobalChannel = 0; 250 } 251 for (i = 0; i < NumConnections; i++) { 252 delete Connection[i]; 253 Connection[i] = 0; 254 } 255 NumConnections = 0; 256 257 //------------------------------------------------------------------------ 258 // Free all real-mode memory 259 //------------------------------------------------------------------------ 260 if (RealMemAllocd) { 261 Free_RealMode_Mem(); 262 RealMemAllocd = 0; 263 } 264 #ifdef FIXIT_CSII // checked - ajw 9/28/98 265 #ifdef WIN32 266 #ifndef WINSOCK_IPX 267 //PG Unload_IPX_Dll(); 268 #endif 269 #endif 270 #endif 271 } /* end of ~IPXManagerClass */ 272 273 274 /*************************************************************************** 275 * IPXManagerClass::Init -- initialization routine * 276 * * 277 * This routine allocates memory, & initializes variables * 278 * * 279 * INPUT: * 280 * none. * 281 * * 282 * OUTPUT: * 283 * 1 = OK, 0 = error * 284 * * 285 * WARNINGS: * 286 * none. * 287 * * 288 * HISTORY: * 289 * 12/20/1994 BR : Created. * 290 *=========================================================================*/ 291 int IPXManagerClass::Init() 292 { 293 int i; 294 295 if (Session.Type != GAME_INTERNET) { 296 297 //------------------------------------------------------------------------ 298 // Error if IPX not installed 299 //------------------------------------------------------------------------ 300 if (!IPXStatus) { 301 return(0); 302 } 303 304 //------------------------------------------------------------------------ 305 // Stop Listening 306 //------------------------------------------------------------------------ 307 if (Listening) { 308 IPXConnClass::Stop_Listening(); 309 Listening = 0; 310 } 311 312 //------------------------------------------------------------------------ 313 // Free Real-mode memory 314 //------------------------------------------------------------------------ 315 if (RealMemAllocd) { 316 Free_RealMode_Mem(); 317 RealMemAllocd = 0; 318 } 319 320 } else { 321 /* 322 ** Pretend IPX is available for Internet games whether it is or not 323 */ 324 IPXStatus = 1; 325 } 326 327 //------------------------------------------------------------------------ 328 // Free protected-mode memory 329 //------------------------------------------------------------------------ 330 if (GlobalChannel) { 331 delete GlobalChannel; 332 GlobalChannel = 0; 333 } 334 for (i = 0; i < NumConnections; i++) { 335 delete Connection[i]; 336 Connection[i] = 0; 337 } 338 NumConnections = 0; 339 340 if (Session.Type != GAME_INTERNET) { 341 //------------------------------------------------------------------------ 342 // Allocate real-mode memory 343 //------------------------------------------------------------------------ 344 if (!Alloc_RealMode_Mem()) return(0); 345 RealMemAllocd = 1; 346 } 347 348 //------------------------------------------------------------------------ 349 // Allocate the Global Channel 350 //------------------------------------------------------------------------ 351 GlobalChannel = new IPXGlobalConnClass (Glb_NumPackets, Glb_NumPackets, 352 Glb_MaxPacketLen, ProductID); 353 if (!GlobalChannel) { 354 return(0); 355 } 356 GlobalChannel->Init(); 357 GlobalChannel->Set_Retry_Delta (RetryDelta); 358 GlobalChannel->Set_Max_Retries (MaxRetries); 359 GlobalChannel->Set_TimeOut (Timeout); 360 361 //------------------------------------------------------------------------ 362 // Configure the IPX Connections 363 //------------------------------------------------------------------------ 364 IPXConnClass::Configure(Socket, ConnectionNum, ListenECB, SendECB, 365 FirstHeaderBuf, SendHeader, FirstDataBuf, SendBuf, Handler, PacketLen); 366 367 //------------------------------------------------------------------------ 368 // Start Listening 369 //------------------------------------------------------------------------ 370 if (Session.Type != GAME_INTERNET) { 371 if (!IPXConnClass::Start_Listening()) return(0); 372 } 373 Listening = 1; 374 375 return(1); 376 377 } /* end of Init */ 378 379 380 /*************************************************************************** 381 * IPXManagerClass::Is_IPX -- tells if IPX is installed or not * 382 * * 383 * INPUT: * 384 * none. * 385 * * 386 * OUTPUT: * 387 * 1 = IPX is installed; 0 = isn't * 388 * * 389 * WARNINGS: * 390 * none. * 391 * * 392 * HISTORY: * 393 * 12/20/1994 BR : Created. * 394 *=========================================================================*/ 395 int IPXManagerClass::Is_IPX(void) 396 { 397 return(IPXStatus); 398 399 } /* end of Is_IPX */ 400 401 402 /*************************************************************************** 403 * IPXManagerClass::Set_Timing -- sets timing for all connections * 404 * * 405 * This will set the timing parameters for all existing connections, and * 406 * all connections created from now on. This allows an application to * 407 * measure the Response_Time while running, and adjust timing accordingly. * 408 * * 409 * INPUT: * 410 * retrydelta value to set for retry delta * 411 * maxretries value to set for max # retries * 412 * timeout value to set for connection timeout * 413 * * 414 * OUTPUT: * 415 * none. * 416 * * 417 * WARNINGS: * 418 * none. * 419 * * 420 * HISTORY: * 421 * 07/02/1995 BR : Created. * 422 *=========================================================================*/ 423 void IPXManagerClass::Set_Timing (unsigned long retrydelta, 424 unsigned long maxretries, unsigned long timeout) 425 { 426 int i; 427 428 RetryDelta = retrydelta; 429 MaxRetries = maxretries; 430 Timeout = timeout; 431 432 if (GlobalChannel) { 433 GlobalChannel->Set_Retry_Delta (RetryDelta); 434 GlobalChannel->Set_Max_Retries (MaxRetries); 435 GlobalChannel->Set_TimeOut (Timeout); 436 } 437 438 for (i = 0; i < NumConnections; i++) { 439 Connection[i]->Set_Retry_Delta (RetryDelta); 440 Connection[i]->Set_Max_Retries (MaxRetries); 441 Connection[i]->Set_TimeOut (Timeout); 442 } 443 444 } /* end of Set_Timing */ 445 446 447 /*************************************************************************** 448 * IPXManagerClass::Create_Connection -- creates a new connection * 449 * * 450 * INPUT: * 451 * id application-specific numerical ID for this connection * 452 * node ptr to IPXNodeIDType (name & address) * 453 * address IPX address for this connection * 454 * * 455 * OUTPUT: * 456 * 1 = OK, 0 = error * 457 * * 458 * WARNINGS: * 459 * Never create a connection with an 'id' of -1. * 460 * * 461 * HISTORY: * 462 * 12/20/1994 BR : Created. * 463 *=========================================================================*/ 464 int IPXManagerClass::Create_Connection(int id, char *name, 465 IPXAddressClass *address) 466 { 467 //------------------------------------------------------------------------ 468 // Error if IPX not installed 469 //------------------------------------------------------------------------ 470 if (!IPXStatus) { 471 return(0); 472 } 473 474 //------------------------------------------------------------------------ 475 // Error if no more room 476 //------------------------------------------------------------------------ 477 if (NumConnections==CONNECT_MAX) { 478 return(0); 479 } 480 481 //------------------------------------------------------------------------ 482 // Create new connection 483 //------------------------------------------------------------------------ 484 Connection[NumConnections] = new IPXConnClass(Pvt_NumPackets, 485 Pvt_NumPackets, Pvt_MaxPacketLen, ProductID, address, id, name); 486 if (!Connection[NumConnections]) { 487 return(0); 488 } 489 490 Connection[NumConnections]->Init (); 491 Connection[NumConnections]->Set_Retry_Delta (RetryDelta); 492 Connection[NumConnections]->Set_Max_Retries (MaxRetries); 493 Connection[NumConnections]->Set_TimeOut (Timeout); 494 495 NumConnections++; 496 497 return(1); 498 499 } /* end of Create_Connection */ 500 501 502 /*************************************************************************** 503 * IPXManagerClass::Delete_Connection -- deletes a connection * 504 * * 505 * INPUT: * 506 * id ID of connection to delete * 507 * * 508 * OUTPUT: * 509 * 1 = OK, 0 = error * 510 * * 511 * WARNINGS: * 512 * none. * 513 * * 514 * HISTORY: * 515 * 12/20/1994 BR : Created. * 516 *=========================================================================*/ 517 int IPXManagerClass::Delete_Connection(int id) 518 { 519 int i,j; 520 521 //------------------------------------------------------------------------ 522 // Error if IPX not installed 523 //------------------------------------------------------------------------ 524 if (!IPXStatus) { 525 return(0); 526 } 527 528 //------------------------------------------------------------------------ 529 // Error if no connections to delete 530 //------------------------------------------------------------------------ 531 if (NumConnections==0) { 532 return(0); 533 } 534 535 //------------------------------------------------------------------------ 536 // Loop through all connections 537 //------------------------------------------------------------------------ 538 for (i = 0; i < NumConnections; i++) { 539 //..................................................................... 540 // If a match, delete it 541 //..................................................................... 542 if (Connection[i]->ID==id) { 543 delete Connection[i]; 544 545 //.................................................................. 546 // Move array elements back one index 547 //.................................................................. 548 for (j = i; j < NumConnections - 1; j++) { 549 Connection[j] = Connection[j+1]; 550 } 551 552 //.................................................................. 553 // Adjust counters 554 //.................................................................. 555 NumConnections--; 556 if (CurConnection >= NumConnections) 557 CurConnection = 0; 558 return(1); 559 } 560 } 561 562 //------------------------------------------------------------------------ 563 // No match; error 564 //------------------------------------------------------------------------ 565 return(0); 566 567 } /* end of Delete_Connection */ 568 569 570 /*************************************************************************** 571 * IPXManagerClass::Num_Connections -- gets the # of connections * 572 * * 573 * INPUT: * 574 * none. * 575 * * 576 * OUTPUT: * 577 * # of connections * 578 * * 579 * WARNINGS: * 580 * none. * 581 * * 582 * HISTORY: * 583 * 01/25/1995 BR : Created. * 584 *=========================================================================*/ 585 int IPXManagerClass::Num_Connections(void) 586 { 587 return(NumConnections); 588 589 } /* end of Num_Connections */ 590 591 592 /*************************************************************************** 593 * IPXManagerClass::Connection_ID -- gets the given connection's ID * 594 * * 595 * INPUT: * 596 * index index of connection to retrieve * 597 * * 598 * OUTPUT: * 599 * ID for that connection, CONNECTION_NONE if invalid index * 600 * * 601 * WARNINGS: * 602 * none. * 603 * * 604 * HISTORY: * 605 * 01/25/1995 BR : Created. * 606 *=========================================================================*/ 607 int IPXManagerClass::Connection_ID(int index) 608 { 609 if (index >= 0 && index < NumConnections) { 610 return(Connection[index]->ID); 611 } 612 else { 613 return(CONNECTION_NONE); 614 } 615 } /* end of Connection_ID */ 616 617 618 /*************************************************************************** 619 * IPXManagerClass::Connection_Name -- retrieves name for given connection * 620 * * 621 * INPUT: * 622 * id ID of connection to get name of * 623 * * 624 * OUTPUT: * 625 * ptr to connection's name, NULL if not found * 626 * * 627 * WARNINGS: * 628 * none. * 629 * * 630 * HISTORY: * 631 * 01/19/1995 BR : Created. * 632 *=========================================================================*/ 633 char *IPXManagerClass::Connection_Name(int id) 634 { 635 int i; 636 637 for (i = 0; i < NumConnections; i++) { 638 if (Connection[i]->ID==id) { 639 return(Connection[i]->Name); 640 } 641 } 642 643 return(NULL); 644 645 } /* end of Connection_Name */ 646 647 648 /*************************************************************************** 649 * IPXManagerClass::Connection_Address -- retrieves connection's address * 650 * * 651 * INPUT: * 652 * id ID of connection to get address for * 653 * * 654 * OUTPUT: * 655 * pointer to IXPAddressClass, NULL if not found * 656 * * 657 * WARNINGS: * 658 * none. * 659 * * 660 * HISTORY: * 661 * 01/19/1995 BR : Created. * 662 *=========================================================================*/ 663 IPXAddressClass * IPXManagerClass::Connection_Address(int id) 664 { 665 int i; 666 667 for (i = 0; i < NumConnections; i++) { 668 if (Connection[i]->ID==id) { 669 return(&Connection[i]->Address); 670 } 671 } 672 673 return(NULL); 674 675 } /* end of Connection_Address */ 676 677 678 /*************************************************************************** 679 * IPXManagerClass::Connection_Index -- gets given connection's index * 680 * * 681 * INPUT: * 682 * ID to retrieve index for * 683 * * 684 * OUTPUT: * 685 * index for this connection, CONNECTION_NONE if not found * 686 * * 687 * WARNINGS: * 688 * none. * 689 * * 690 * HISTORY: * 691 * 01/25/1995 BR : Created. * 692 *=========================================================================*/ 693 int IPXManagerClass::Connection_Index(int id) 694 { 695 int i; 696 697 for (i = 0; i < NumConnections; i++) { 698 if (Connection[i]->ID==id) { 699 return(i); 700 } 701 } 702 703 return(CONNECTION_NONE); 704 705 } /* end of Connection_Index */ 706 707 708 /*************************************************************************** 709 * IPXManagerClass::Set_Connection_Parms -- sets connection's name & id * 710 * * 711 * INPUT: * 712 * index connection index * 713 * id new connection ID * 714 * name new connection name * 715 * * 716 * OUTPUT: * 717 * none. * 718 * * 719 * WARNINGS: * 720 * none. * 721 * * 722 * HISTORY: * 723 * 01/25/1995 BR : Created. * 724 *=========================================================================*/ 725 void IPXManagerClass::Set_Connection_Parms(int index, int id, char *name) 726 { 727 if (index >= NumConnections) 728 return; 729 730 Connection[index]->ID = id; 731 strcpy(Connection[index]->Name,name); 732 733 } /* end of Set_Connection_Parms */ 734 735 736 /*************************************************************************** 737 * IPXManagerClass::Send_Global_Message -- sends a Global Message * 738 * * 739 * INPUT: * 740 * buf buffer to send * 741 * buflen length of buf * 742 * ack_req 1 = ACK required; 0 = no ACK required * 743 * address address to send to; NULL = broadcast * 744 * * 745 * OUTPUT: * 746 * 1 = OK, 0 = error * 747 * * 748 * WARNINGS: * 749 * none. * 750 * * 751 * HISTORY: * 752 * 01/25/1995 BR : Created. * 753 *=========================================================================*/ 754 int IPXManagerClass::Send_Global_Message(void *buf, int buflen, 755 int ack_req, IPXAddressClass *address) 756 { 757 int rc; 758 759 //------------------------------------------------------------------------ 760 // Error if IPX not installed or not Listening 761 //------------------------------------------------------------------------ 762 if (!IPXStatus || !Listening) return(0); 763 764 rc = GlobalChannel->Send_Packet (buf, buflen, address, ack_req); 765 if (!rc) { 766 SendOverflows++; 767 } 768 769 return(rc); 770 771 } /* end of Send_Global_Message */ 772 773 774 /*************************************************************************** 775 * IPXManagerClass::Get_Global_Message -- polls the Global Message queue * 776 * * 777 * INPUT: * 778 * buf buffer to store received packet * 779 * buflen length of data placed in 'buf' * 780 * address IPX address of sender * 781 * product_id product ID of sender * 782 * * 783 * OUTPUT: * 784 * 1 = OK, 0 = error * 785 * * 786 * WARNINGS: * 787 * none. * 788 * * 789 * HISTORY: * 790 * 01/25/1995 BR : Created. * 791 *=========================================================================*/ 792 int IPXManagerClass::Get_Global_Message(void *buf, int *buflen, 793 IPXAddressClass *address, unsigned short *product_id) 794 { 795 //------------------------------------------------------------------------ 796 // Error if IPX not installed or not Listening 797 //------------------------------------------------------------------------ 798 if (!IPXStatus || !Listening) return(0); 799 800 return(GlobalChannel->Get_Packet (buf, buflen, address, product_id)); 801 802 } /* end of Get_Global_Message */ 803 804 805 /*************************************************************************** 806 * IPXManagerClass::Send_Private_Message -- Sends a Private Message * 807 * * 808 * INPUT: * 809 * buf buffer to send * 810 * buflen length of 'buf' * 811 * conn_id connection ID to send to (CONNECTION_NONE = all) * 812 * ack_req 1 = ACK required; 0 = no ACK required * 813 * * 814 * OUTPUT: * 815 * 1 = OK, 0 = error * 816 * * 817 * WARNINGS: * 818 * none. * 819 * * 820 * HISTORY: * 821 * 01/25/1995 BR : Created. * 822 *=========================================================================*/ 823 int IPXManagerClass::Send_Private_Message(void *buf, int buflen, int ack_req, 824 int conn_id) 825 { 826 int i; // loop counter 827 int connect_idx; // index of channel to send to, if specified 828 829 //------------------------------------------------------------------------ 830 // Error if IPX not installed or not Listening 831 //------------------------------------------------------------------------ 832 833 if (!IPXStatus || !Listening || (NumConnections==0)) { 834 return(0); 835 } 836 837 //------------------------------------------------------------------------ 838 // Send the message to all connections 839 //------------------------------------------------------------------------ 840 if (conn_id==CONNECTION_NONE) { 841 //..................................................................... 842 // Check for room in all connections 843 //..................................................................... 844 for (i = 0; i < NumConnections; i++) { 845 if (Connection[i]->Queue->Num_Send() == 846 Connection[i]->Queue->Max_Send()) { 847 SendOverflows++; 848 return(0); 849 } 850 } 851 852 //..................................................................... 853 // Send packet to all connections 854 //..................................................................... 855 for (i = 0; i < NumConnections; i++) { 856 Connection[i]->Send_Packet (buf, buflen, ack_req); 857 } 858 return(1); 859 } 860 861 //------------------------------------------------------------------------ 862 // Send the message to the specified connection 863 //------------------------------------------------------------------------ 864 else { 865 connect_idx = Connection_Index (conn_id); 866 if (connect_idx == CONNECTION_NONE) { 867 SendOverflows++; 868 return(0); 869 } 870 871 //..................................................................... 872 // Check for room in the connection 873 //..................................................................... 874 if (Connection[connect_idx]->Queue->Num_Send() == 875 Connection[connect_idx]->Queue->Max_Send()) { 876 SendOverflows++; 877 return(0); 878 } 879 880 //..................................................................... 881 // Send the packet to that connection 882 //..................................................................... 883 Connection[connect_idx]->Send_Packet (buf, buflen, ack_req); 884 return(1); 885 } 886 887 } /* end of Send_Private_Message */ 888 889 890 /*************************************************************************** 891 * IPXManagerClass::Get_Private_Message -- Polls the Private Message queue * 892 * * 893 * INPUT: * 894 * buf buffer to store incoming packet * 895 * buflen length of data placed in 'buf' * 896 * conn_id filled in with connection ID of sender * 897 * * 898 * OUTPUT: * 899 * 1 = OK, 0 = error * 900 * * 901 * WARNINGS: * 902 * none. * 903 * * 904 * HISTORY: * 905 * 01/25/1995 BR : Created. * 906 *=========================================================================*/ 907 int IPXManagerClass::Get_Private_Message(void *buf, int *buflen, int *conn_id) 908 { 909 int i; 910 int rc; 911 int c_id; 912 913 //------------------------------------------------------------------------ 914 // Error if IPX not installed or not Listening 915 //------------------------------------------------------------------------ 916 if (!IPXStatus || !Listening || (NumConnections==0)) { 917 return(0); 918 } 919 920 //------------------------------------------------------------------------ 921 // Safety check: ensure CurConnection is in range. 922 //------------------------------------------------------------------------ 923 if (CurConnection >= NumConnections) { 924 CurConnection = 0; 925 } 926 927 //------------------------------------------------------------------------ 928 // Scan all connections for a received packet, starting with 'CurConnection' 929 //------------------------------------------------------------------------ 930 for (i = 0; i < NumConnections; i++) { 931 932 //..................................................................... 933 // Check this connection for a packet 934 //..................................................................... 935 rc = Connection[CurConnection]->Get_Packet (buf, buflen); 936 c_id = Connection[CurConnection]->ID; 937 938 //..................................................................... 939 // Increment CurConnection to the next connection index 940 //..................................................................... 941 CurConnection++; 942 if (CurConnection >= NumConnections) { 943 CurConnection = 0; 944 } 945 946 //..................................................................... 947 // If we got a packet, return the connection ID 948 //..................................................................... 949 if (rc) { 950 (*conn_id) = c_id; 951 return(1); 952 } 953 } 954 955 return(0); 956 957 } /* end of Get_Private_Message */ 958 959 960 /*************************************************************************** 961 * IPXManagerClass::Service -- main polling routine for IPX Connections * 962 * * 963 * INPUT: * 964 * none. * 965 * * 966 * OUTPUT: * 967 * 1 = OK, 0 = error * 968 * * 969 * WARNINGS: * 970 * none. * 971 * * 972 * HISTORY: * 973 * 01/25/1995 BR : Created. * 974 *=========================================================================*/ 975 int IPXManagerClass::Service(void) 976 { 977 int rc = 1; 978 int i; 979 CommHeaderType *packet; 980 int packetlen; 981 IPXAddressClass address; 982 983 #ifdef WINSOCK_IPX 984 985 986 unsigned char temp_receive_buffer[1024]; 987 int temp_receive_buffer_len; 988 int temp_address_len; 989 990 991 char temp_address [128]; 992 993 if ( PacketTransport ) { 994 995 do { 996 temp_receive_buffer_len = sizeof (temp_receive_buffer); 997 temp_address_len = sizeof (temp_address); 998 packetlen = PacketTransport->Read ( temp_receive_buffer, temp_receive_buffer_len, temp_address, temp_address_len ); 999 if ( packetlen ) { 1000 CurDataBuf = (char*)temp_receive_buffer; 1001 address = *((IPXAddressClass*) temp_address); 1002 1003 packet = (CommHeaderType *)CurDataBuf; 1004 if (packet->MagicNumber == GlobalChannel->Magic_Num()) { 1005 1006 /* 1007 ** Put the packet in the Global Queue 1008 */ 1009 if (!GlobalChannel->Receive_Packet (packet, packetlen, &address)) 1010 ReceiveOverflows++; 1011 } else { 1012 if (packet->MagicNumber == ProductID) { 1013 1014 /* 1015 ** Find the Private Queue that this packet is for 1016 */ 1017 bool found_address = false; 1018 for (i = 0; i < NumConnections; i++) { 1019 if (Connection[i]->Address == address) { 1020 found_address = true; 1021 if (!Connection[i]->Receive_Packet (packet, packetlen)) 1022 ReceiveOverflows++; 1023 break; 1024 } 1025 } 1026 if( Session.Type == GAME_INTERNET ) 1027 { 1028 /* 1029 ** This packet came from an unknown source. If it looks like one of our players 1030 ** packets then it might be from a player whos IP has changed. 1031 */ 1032 if (!found_address) { 1033 if (packet->Code == ConnectionClass::PACKET_DATA_NOACK){ 1034 /* 1035 ** Magic number and packet code are valid. It's probably a C&C packet. 1036 */ 1037 EventClass *event = (EventClass*) (((char*) packet) + sizeof (CommHeaderType)); 1038 1039 /* 1040 ** If this is a framesync packet then grab the address and match it to an existing player. 1041 */ 1042 if (event->Type == EventClass::FRAMESYNC) { 1043 int id = event->ID; 1044 1045 assert (id != PlayerPtr->ID); 1046 for ( int i=1 ; i<Session.Players.Count() ; i++) { 1047 if (Session.Players[i]->Player.ID == id) { 1048 1049 int iConnectionIndex = Connection_Index(id); 1050 if( iConnectionIndex != CONNECTION_NONE ) // (else Create_Connections() has not yet been called) 1051 { 1052 /* 1053 ** Found a likely candidate. Update his address. It should be OK to drop this 1054 ** packet since it's a framesync packet and will will pick up the next one. 1055 */ 1056 Session.Players[i]->Address = address; 1057 Connection[iConnectionIndex]->Address = address; 1058 } 1059 break; 1060 } 1061 } 1062 } 1063 } 1064 } 1065 } 1066 } 1067 } 1068 } 1069 1070 } while (packetlen); 1071 1072 } 1073 1074 1075 1076 1077 #else //WINSOCK_IPX 1078 1079 #ifdef WIN32 1080 1081 unsigned char temp_receive_buffer[1024]; 1082 int recv_length; 1083 1084 if (Winsock.Get_Connected() || Special.IsFromWChat) { 1085 1086 if (!Winsock.Get_Connected()) return (0); 1087 1088 /* 1089 ** This is an internet connection so get the packets from winsock 1090 */ 1091 while ((recv_length = Winsock.Read(temp_receive_buffer, 1024))!=0) { 1092 1093 CurHeaderBuf = NULL; 1094 CurDataBuf = (char*)&temp_receive_buffer[0]; 1095 1096 /*..................................................................... 1097 Compute the length of the packet (byte-swap the length in the IPX hdr) 1098 .....................................................................*/ 1099 packetlen = recv_length; 1100 1101 /*..................................................................... 1102 Extract the sender's address from the IPX header 1103 .....................................................................*/ 1104 address.Set_Address (CurHeaderBuf); 1105 1106 /*..................................................................... 1107 Examine the Magic Number of the received packet to determine if this 1108 packet goes into the Global Queue, or into one of the Private Queues 1109 .....................................................................*/ 1110 packet = (CommHeaderType *)CurDataBuf; 1111 if (packet->MagicNumber == GlobalChannel->Magic_Num()) { 1112 /*.................................................................. 1113 Put the packet in the Global Queue 1114 ..................................................................*/ 1115 if (!GlobalChannel->Receive_Packet (packet, packetlen, &address)) 1116 ReceiveOverflows++; 1117 } else { 1118 if (packet->MagicNumber == ProductID) { 1119 /*.................................................................. 1120 Find the Private Queue that this packet is for 1121 ..................................................................*/ 1122 for (i = 0; i < NumConnections; i++) { 1123 if (Connection[i]->Address == address) { 1124 if (!Connection[i]->Receive_Packet (packet, packetlen)) 1125 ReceiveOverflows++; 1126 break; 1127 } 1128 } 1129 } 1130 } 1131 1132 } 1133 } else { 1134 #if(0)//PG 1135 while (IPX_Get_Outstanding_Buffer95(&temp_receive_buffer[0])) { 1136 1137 CurHeaderBuf = (IPXHEADER*)&temp_receive_buffer[0]; 1138 CurDataBuf = (char*)&temp_receive_buffer[sizeof(IPXHeaderType)]; 1139 1140 /*..................................................................... 1141 Compute the length of the packet (byte-swap the length in the IPX hdr) 1142 .....................................................................*/ 1143 packetlen = ((CurHeaderBuf->Length & 0xff) << 8) | 1144 (CurHeaderBuf->Length >> 8); 1145 packetlen -= sizeof(IPXHeaderType); 1146 1147 /*..................................................................... 1148 Extract the sender's address from the IPX header 1149 .....................................................................*/ 1150 address.Set_Address (CurHeaderBuf); 1151 1152 /*..................................................................... 1153 Examine the Magic Number of the received packet to determine if this 1154 packet goes into the Global Queue, or into one of the Private Queues 1155 .....................................................................*/ 1156 packet = (CommHeaderType *)CurDataBuf; 1157 if (packet->MagicNumber == GlobalChannel->Magic_Num()) { 1158 /*.................................................................. 1159 Put the packet in the Global Queue 1160 ..................................................................*/ 1161 if (!GlobalChannel->Receive_Packet (packet, packetlen, &address)) 1162 ReceiveOverflows++; 1163 } else { 1164 if (packet->MagicNumber == ProductID) { 1165 /*.................................................................. 1166 Find the Private Queue that this packet is for 1167 ..................................................................*/ 1168 for (i = 0; i < NumConnections; i++) { 1169 if (Connection[i]->Address == address) { 1170 if (!Connection[i]->Receive_Packet (packet, packetlen)) 1171 ReceiveOverflows++; 1172 break; 1173 } 1174 } 1175 } 1176 } 1177 } 1178 #endif 1179 } 1180 1181 1182 #else //WIN32 1183 1184 1185 //------------------------------------------------------------------------ 1186 // Error if IPX not installed or not Listening 1187 //------------------------------------------------------------------------ 1188 if (!IPXStatus || !Listening) { 1189 return(0); 1190 } 1191 1192 //------------------------------------------------------------------------ 1193 // Loop until there are no more packets to process. 1194 //------------------------------------------------------------------------ 1195 while (1) { 1196 1197 //..................................................................... 1198 // Check the BufferFlags for the "current" buffer; if it's empty, 1199 // break; out of the loop. 1200 //..................................................................... 1201 if (BufferFlags[CurIndex]==0) { 1202 break; 1203 } 1204 1205 //..................................................................... 1206 // Compute the length of the packet (byte-swap the length in the IPX hdr) 1207 //..................................................................... 1208 packetlen = ((CurHeaderBuf->Length & 0xff) << 8) | 1209 (CurHeaderBuf->Length >> 8); 1210 packetlen -= sizeof(IPXHeaderType); 1211 1212 //..................................................................... 1213 // Extract the sender's address from the IPX header 1214 //..................................................................... 1215 address.Set_Address (CurHeaderBuf); 1216 1217 //..................................................................... 1218 // Examine the Magic Number of the received packet to determine if this 1219 // packet goes into the Global Queue, or into one of the Private Queues 1220 //..................................................................... 1221 packet = (CommHeaderType *)CurDataBuf; 1222 if (packet->MagicNumber == GlobalChannel->Magic_Num()) { 1223 1224 //.................................................................. 1225 // Put the packet in the Global Queue 1226 //.................................................................. 1227 if (!GlobalChannel->Receive_Packet (packet, packetlen, &address)) { 1228 ReceiveOverflows++; 1229 } 1230 } 1231 1232 //..................................................................... 1233 // Find the Private Queue that this packet is for 1234 //..................................................................... 1235 else if (packet->MagicNumber == ProductID) { 1236 for (i = 0; i < NumConnections; i++) { 1237 if (Connection[i]->Address == address) { 1238 if (!Connection[i]->Receive_Packet (packet, packetlen)) { 1239 ReceiveOverflows++; 1240 } 1241 break; 1242 } 1243 } 1244 } 1245 1246 //..................................................................... 1247 // Set the current BufferFlags to 0 (since we've cleaned out this buffer) 1248 //..................................................................... 1249 BufferFlags[CurIndex] = 0; 1250 1251 //..................................................................... 1252 // Go to the next packet buffer 1253 //..................................................................... 1254 CurIndex++; 1255 CurHeaderBuf = (IPXHeaderType *)(((char *)CurHeaderBuf) + FullPacketLen); 1256 CurDataBuf = ((char *)CurDataBuf) + FullPacketLen; 1257 if (CurIndex >= NumBufs) { 1258 CurHeaderBuf = FirstHeaderBuf; 1259 CurDataBuf = FirstDataBuf; 1260 CurIndex = 0; 1261 } 1262 } 1263 1264 #endif //WIN32 1265 #endif //WINSOCK_IPX 1266 1267 //------------------------------------------------------------------------ 1268 // Service all connections. If a connection reports that it's gone "bad", 1269 // report an error to the caller. If it's the Global Channel, un-queue the 1270 // send entry that's holding things up. This will keep the Global Channel 1271 // from being clogged by one un-ACK'd outgoing packet. 1272 //------------------------------------------------------------------------ 1273 if (GlobalChannel) { 1274 if (!GlobalChannel->Service()) { 1275 GlobalChannel->Queue->UnQueue_Send (NULL, NULL, 0); 1276 rc = 0; 1277 } 1278 } 1279 for (i = 0; i < NumConnections; i++) { 1280 if (!Connection[i]->Service()) { 1281 rc = 0; 1282 BadConnection = Connection[i]->ID; 1283 } 1284 } 1285 1286 if (rc) { 1287 BadConnection = CONNECTION_NONE; 1288 } 1289 1290 return(rc); 1291 1292 } /* end of Service */ 1293 1294 /*************************************************************************** 1295 * IPXManagerClass::Get_Bad_Connection -- returns bad connection ID * 1296 * * 1297 * INPUT: * 1298 * none. * 1299 * * 1300 * OUTPUT: * 1301 * ID of bad connection; CONNECTION_NONE if none. * 1302 * * 1303 * WARNINGS: * 1304 * none. * 1305 * * 1306 * HISTORY: * 1307 * 05/04/1995 BRR : Created. * 1308 *=========================================================================*/ 1309 int IPXManagerClass::Get_Bad_Connection(void) 1310 { 1311 return(BadConnection); 1312 1313 } /* end of Get_Bad_Connection */ 1314 1315 1316 /*************************************************************************** 1317 * IPXManagerClass::Global_Num_Send -- reports # entries in send queue * 1318 * * 1319 * INPUT: * 1320 * none. * 1321 * * 1322 * OUTPUT: * 1323 * # entries in the Global Send Queue * 1324 * * 1325 * WARNINGS: * 1326 * none. * 1327 * * 1328 * HISTORY: * 1329 * 01/25/1995 BR : Created. * 1330 *=========================================================================*/ 1331 int IPXManagerClass::Global_Num_Send(void) 1332 { 1333 //------------------------------------------------------------------------ 1334 // Error if IPX not installed or not Listening 1335 //------------------------------------------------------------------------ 1336 if (!IPXStatus || !Listening) { 1337 return(0); 1338 } 1339 1340 return(GlobalChannel->Queue->Num_Send()); 1341 1342 } /* end of Global_Num_Send */ 1343 1344 1345 /*************************************************************************** 1346 * IPXManagerClass::Global_Num_Receive -- reports # entries in recv queue * 1347 * * 1348 * INPUT: * 1349 * none. * 1350 * * 1351 * OUTPUT: * 1352 * # entries in the Global Receive Queue * 1353 * * 1354 * WARNINGS: * 1355 * none. * 1356 * * 1357 * HISTORY: * 1358 * 01/25/1995 BR : Created. * 1359 *=========================================================================*/ 1360 int IPXManagerClass::Global_Num_Receive(void) 1361 { 1362 //------------------------------------------------------------------------ 1363 // Error if IPX not installed or not Listening 1364 //------------------------------------------------------------------------ 1365 if (!IPXStatus || !Listening) { 1366 return(0); 1367 } 1368 1369 return(GlobalChannel->Queue->Num_Receive()); 1370 1371 } /* end of Global_Num_Receive */ 1372 1373 1374 /*************************************************************************** 1375 * IPXManagerClass::Private_Num_Send -- reports # entries in send queue * 1376 * * 1377 * INPUT: * 1378 * # entries in the Private Send Queue * 1379 * * 1380 * OUTPUT: * 1381 * 1 = OK, 0 = error * 1382 * * 1383 * WARNINGS: * 1384 * none. * 1385 * * 1386 * HISTORY: * 1387 * 01/25/1995 BR : Created. * 1388 *=========================================================================*/ 1389 int IPXManagerClass::Private_Num_Send(int id) 1390 { 1391 int i; 1392 int maxnum; 1393 1394 //------------------------------------------------------------------------ 1395 // Error if IPX not installed or not Listening 1396 //------------------------------------------------------------------------ 1397 if (!IPXStatus || !Listening || (NumConnections==0)) { 1398 return(0); 1399 } 1400 1401 //------------------------------------------------------------------------ 1402 // If connection ID specified, return that connection's # of packets 1403 //------------------------------------------------------------------------ 1404 if (id != CONNECTION_NONE) { 1405 i = Connection_Index(id); 1406 if (i != CONNECTION_NONE) { 1407 return(Connection[i]->Queue->Num_Send()); 1408 } 1409 else { 1410 return(0); 1411 } 1412 1413 } 1414 1415 //------------------------------------------------------------------------ 1416 // Otherwise, return the max # of all connections 1417 //------------------------------------------------------------------------ 1418 else { 1419 maxnum = 0; 1420 for (i = 0; i < NumConnections; i++) { 1421 if (Connection[i]->Queue->Num_Send() > maxnum) { 1422 maxnum = Connection[i]->Queue->Num_Send(); 1423 } 1424 } 1425 return(maxnum); 1426 } 1427 1428 } /* end of Private_Num_Send */ 1429 1430 1431 /*************************************************************************** 1432 * IPXManagerClass::Private_Num_Receive -- reports # entries in recv queue * 1433 * * 1434 * INPUT: * 1435 * id ID of connection to query * 1436 * * 1437 * OUTPUT: * 1438 * # entries in the Private Receive Queue * 1439 * * 1440 * WARNINGS: * 1441 * none. * 1442 * * 1443 * HISTORY: * 1444 * 01/25/1995 BR : Created. * 1445 *=========================================================================*/ 1446 int IPXManagerClass::Private_Num_Receive(int id) 1447 { 1448 int i; 1449 int maxnum; 1450 1451 //------------------------------------------------------------------------ 1452 // Error if IPX not installed or not Listening 1453 //------------------------------------------------------------------------ 1454 if (!IPXStatus || !Listening || (NumConnections==0)) 1455 return(0); 1456 1457 //------------------------------------------------------------------------ 1458 // If connection ID specified, return that connection's # of packets 1459 //------------------------------------------------------------------------ 1460 if (id != CONNECTION_NONE) { 1461 i = Connection_Index(id); 1462 if (i != CONNECTION_NONE) { 1463 return(Connection[i]->Queue->Num_Receive()); 1464 } 1465 else { 1466 return(0); 1467 } 1468 1469 } 1470 1471 //------------------------------------------------------------------------ 1472 // Otherwise, return the max # of all connections 1473 //------------------------------------------------------------------------ 1474 else { 1475 maxnum = 0; 1476 for (i = 0; i < NumConnections; i++) { 1477 if (Connection[i]->Queue->Num_Receive() > maxnum) { 1478 maxnum = Connection[i]->Queue->Num_Receive(); 1479 } 1480 } 1481 return(maxnum); 1482 } 1483 1484 } /* end of Private_Num_Receive */ 1485 1486 1487 /*************************************************************************** 1488 * IPXManagerClass::Set_Socket -- sets socket ID for all connections * 1489 * * 1490 * INPUT: * 1491 * socket new socket ID to use * 1492 * * 1493 * OUTPUT: * 1494 * none. * 1495 * * 1496 * WARNINGS: * 1497 * Do not call this function after communications have started; you * 1498 * must call it before calling Init(). * 1499 * The socket number is byte-swapped, since IPX requires socket ID's * 1500 * to be stored high/low. * 1501 * * 1502 * HISTORY: * 1503 * 01/25/1995 BR : Created. * 1504 *=========================================================================*/ 1505 void IPXManagerClass::Set_Socket(unsigned short socket) 1506 { 1507 Socket = (unsigned short)( (((unsigned long)socket & 0x00ff) << 8) | 1508 (((unsigned long)socket & 0xff00) >> 8)); 1509 1510 } /* end of Set_Socket */ 1511 1512 1513 /*************************************************************************** 1514 * IPXManagerClass::Response_Time -- Returns largest Avg Response Time * 1515 * * 1516 * INPUT: * 1517 * none. * 1518 * * 1519 * OUTPUT: * 1520 * largest avg response time * 1521 * * 1522 * WARNINGS: * 1523 * none. * 1524 * * 1525 * HISTORY: * 1526 * 05/04/1995 BRR : Created. * 1527 *=========================================================================*/ 1528 unsigned long IPXManagerClass::Response_Time(void) 1529 { 1530 unsigned long resp; 1531 unsigned long maxresp = 0; 1532 int i; 1533 1534 for (i = 0; i < NumConnections; i++) { 1535 resp = Connection[i]->Queue->Avg_Response_Time(); 1536 if (resp > maxresp) { 1537 maxresp = resp; 1538 } 1539 } 1540 1541 return(maxresp); 1542 1543 } /* end of Response_Time */ 1544 1545 1546 /*************************************************************************** 1547 * IPXManagerClass::Global_Response_Time -- Returns Avg Response Time * 1548 * * 1549 * INPUT: * 1550 * none. * 1551 * * 1552 * OUTPUT: * 1553 * avg global channel response time * 1554 * * 1555 * WARNINGS: * 1556 * none. * 1557 * * 1558 * HISTORY: * 1559 * 05/04/1995 BRR : Created. * 1560 *=========================================================================*/ 1561 unsigned long IPXManagerClass::Global_Response_Time(void) 1562 { 1563 if (GlobalChannel) { 1564 return (GlobalChannel->Queue->Avg_Response_Time()); 1565 } 1566 else { 1567 return (0); 1568 } 1569 1570 } /* end of Global_Response_Time */ 1571 1572 1573 /*************************************************************************** 1574 * IPXManagerClass::Reset_Response_Time -- Reset response time * 1575 * * 1576 * INPUT: * 1577 * none. * 1578 * * 1579 * OUTPUT: * 1580 * none. * 1581 * * 1582 * WARNINGS: * 1583 * none. * 1584 * * 1585 * HISTORY: * 1586 * 05/04/1995 BRR : Created. * 1587 *=========================================================================*/ 1588 void IPXManagerClass::Reset_Response_Time(void) 1589 { 1590 int i; 1591 1592 for (i = 0; i < NumConnections; i++) { 1593 Connection[i]->Queue->Reset_Response_Time(); 1594 } 1595 1596 if (GlobalChannel) 1597 GlobalChannel->Queue->Reset_Response_Time(); 1598 1599 } /* end of Reset_Response_Time */ 1600 1601 1602 /*************************************************************************** 1603 * IPXManagerClass::Oldest_Send -- gets ptr to oldest send buf * 1604 * * 1605 * INPUT: * 1606 * none. * 1607 * * 1608 * OUTPUT: * 1609 * buf ptr * 1610 * * 1611 * WARNINGS: * 1612 * none. * 1613 * * 1614 * HISTORY: * 1615 * 05/04/1995 BRR : Created. * 1616 *=========================================================================*/ 1617 void * IPXManagerClass::Oldest_Send(void) 1618 { 1619 int i,j; 1620 unsigned long time; 1621 unsigned long mintime = 0xffffffff; 1622 SendQueueType *send_entry; // ptr to send entry header 1623 CommHeaderType *packet; 1624 void *buf = NULL; 1625 1626 for (i = 0; i < NumConnections; i++) { 1627 1628 send_entry = NULL; 1629 1630 for (j = 0; j < Connection[i]->Queue->Num_Send(); j++) { 1631 send_entry = Connection[i]->Queue->Get_Send(j); 1632 if (send_entry) { 1633 packet = (CommHeaderType *)send_entry->Buffer; 1634 if (packet->Code == ConnectionClass::PACKET_DATA_ACK && 1635 send_entry->IsACK == 0) { 1636 break; 1637 } 1638 else { 1639 send_entry = NULL; 1640 } 1641 } 1642 } 1643 1644 if (send_entry!=NULL) { 1645 1646 time = send_entry->FirstTime; 1647 1648 if (time < mintime) { 1649 mintime = time; 1650 buf = send_entry->Buffer; 1651 } 1652 } 1653 } 1654 1655 return(buf); 1656 1657 } /* end of Oldest_Send */ 1658 1659 1660 /*************************************************************************** 1661 * IPXManagerClass::Set_Bridge -- prepares to cross a bridge * 1662 * * 1663 * This routine is designed to prevent the connection from having to * 1664 * call Get_Local_Target, except the minimum number of times, since that * 1665 * routine is buggy & goes away for long periods sometimes. * 1666 * * 1667 * INPUT: * 1668 * bridge network number of the destination bridge * 1669 * * 1670 * OUTPUT: * 1671 * none * 1672 * * 1673 * WARNINGS: * 1674 * none * 1675 * * 1676 * HISTORY: * 1677 * 07/06/1995 BRR : Created. * 1678 *=========================================================================*/ 1679 void IPXManagerClass::Set_Bridge(NetNumType bridge) 1680 { 1681 if (GlobalChannel) { 1682 GlobalChannel->Set_Bridge(bridge); 1683 } 1684 1685 } /* end of Set_Bridge */ 1686 1687 1688 /*************************************************************************** 1689 * IPXManagerClass::Configure_Debug -- sets up special debug values * 1690 * * 1691 * Mono_Debug_Print2() can look into a packet to pull out a particular * 1692 * ID, and can print both that ID and a string corresponding to * 1693 * that ID. This routine configures these values so it can find * 1694 * and decode the ID. This ID is used in addition to the normal * 1695 * CommHeaderType values. * 1696 * * 1697 * INPUT: * 1698 * index connection index to configure (-1 = Global Channel) * 1699 * type_offset ID's byte offset into packet * 1700 * type_size size of ID, in bytes; 0 if none * 1701 * names ptr to array of names; use ID as an index into this * 1702 * namestart numerical value of 1st name in the array * 1703 * namecount # in the names array; 0 if none. * 1704 * * 1705 * OUTPUT: * 1706 * none. * 1707 * * 1708 * WARNINGS: * 1709 * Names shouldn't be longer than 12 characters. * 1710 * * 1711 * HISTORY: * 1712 * 05/31/1995 BRR : Created. * 1713 *=========================================================================*/ 1714 void IPXManagerClass::Configure_Debug(int index, int type_offset, 1715 int type_size, char **names, int namestart, int namecount) 1716 { 1717 if (index == -1) { 1718 GlobalChannel->Queue->Configure_Debug (type_offset, type_size, names, 1719 namestart, namecount); 1720 } 1721 else if (Connection[index]) { 1722 Connection[index]->Queue->Configure_Debug (type_offset, type_size, names, 1723 namestart, namecount); 1724 } 1725 1726 } /* end of Configure_Debug */ 1727 1728 1729 /*************************************************************************** 1730 * IPXManagerClass::Mono_Debug_Print -- debug output routine * 1731 * * 1732 * INPUT: * 1733 * index index of connection to display (-1 = Global Channel) * 1734 * refresh 1 = complete screen refresh * 1735 * * 1736 * OUTPUT: * 1737 * 1 = OK, 0 = error * 1738 * * 1739 * WARNINGS: * 1740 * none. * 1741 * * 1742 * HISTORY: * 1743 * 01/25/1995 BR : Created. * 1744 *=========================================================================*/ 1745 void IPXManagerClass::Mono_Debug_Print(int index, int refresh) 1746 { 1747 #ifdef WWLIB32_H 1748 char txt[80]; 1749 int i; 1750 1751 if (index == -1) 1752 GlobalChannel->Queue->Mono_Debug_Print (refresh); 1753 1754 else if (Connection[index]) 1755 Connection[index]->Queue->Mono_Debug_Print (refresh); 1756 1757 if (refresh) { 1758 Mono_Set_Cursor (20,1); 1759 Mono_Printf ("IPX Queue:"); 1760 1761 Mono_Set_Cursor (9,2); 1762 Mono_Printf ("Average Response Time:"); 1763 1764 Mono_Set_Cursor (43,1); 1765 Mono_Printf ("Send Overflows:"); 1766 1767 Mono_Set_Cursor (40,2); 1768 Mono_Printf ("Receive Overflows:"); 1769 1770 } 1771 1772 Mono_Set_Cursor (32,1); 1773 Mono_Printf ("%d",index); 1774 1775 Mono_Set_Cursor (32,2); 1776 if (index == -1) { 1777 Mono_Printf ("%d ", GlobalChannel->Queue->Avg_Response_Time()); 1778 } 1779 else { 1780 Mono_Printf ("%d ", Connection[index]->Queue->Avg_Response_Time()); 1781 } 1782 1783 Mono_Set_Cursor (59,1); 1784 Mono_Printf ("%d ", SendOverflows); 1785 1786 Mono_Set_Cursor (59,2); 1787 Mono_Printf ("%d ", ReceiveOverflows); 1788 1789 for (i = 0; i < NumBufs; i++) { 1790 if (BufferFlags[i]) { 1791 txt[i] = 'X'; 1792 } 1793 else { 1794 txt[i] = '_'; 1795 } 1796 } 1797 txt[i] = 0; 1798 Mono_Set_Cursor ((80-NumBufs)/2,3); 1799 Mono_Printf ("%s",txt); 1800 1801 #else 1802 index = index; 1803 refresh = refresh; 1804 #endif 1805 1806 } /* end of Mono_Debug_Print */ 1807 1808 1809 /*************************************************************************** 1810 * IPXManagerClass::Alloc_RealMode_Mem -- allocates real-mode memory * 1811 * * 1812 * INPUT: * 1813 * none. * 1814 * * 1815 * OUTPUT: * 1816 * 1 = OK, 0 = error * 1817 * * 1818 * WARNINGS: * 1819 * none. * 1820 * * 1821 * HISTORY: * 1822 * 12/20/1994 BR : Created. * 1823 *=========================================================================*/ 1824 int IPXManagerClass::Alloc_RealMode_Mem(void) 1825 { 1826 1827 #ifdef WIN32 1828 return (1); 1829 #else 1830 1831 union REGS regs; 1832 struct SREGS sregs; 1833 int size; // required size of allocation 1834 unsigned char *realmode; // start addresses of real-mode data 1835 int realmodelen; // length of real-mode data 1836 unsigned long func_val; 1837 char *p; // for parsing buffer 1838 int i; 1839 1840 //------------------------------------------------------------------------ 1841 // Compute # of buffers we need to allocate, & the max size of each one 1842 //------------------------------------------------------------------------ 1843 NumBufs = Glb_NumPackets + (Pvt_NumPackets * CONNECT_MAX); 1844 1845 PacketLen = Glb_MaxPacketLen + sizeof (GlobalHeaderType); 1846 if (Pvt_MaxPacketLen + sizeof (CommHeaderType) > PacketLen) 1847 PacketLen = Pvt_MaxPacketLen + sizeof (CommHeaderType); 1848 1849 FullPacketLen = PacketLen + sizeof(IPXHeaderType); 1850 1851 //------------------------------------------------------------------------ 1852 // Compute the size of everything we'll ever need, allocate it in one big 1853 // chunk. The memory is used as follows: 1854 // - Real-mode assembly IPX callback routine, plus its data, 1855 // (which includes the ListenECB) 1856 // - Array of IPX Packet buffers (IPXHeader plus data buffer) 1857 // - SendECB: ECB for sending 1858 // - SendHeader: IPX Header for sending 1859 // - SendBuf: Packet buffer for sending 1860 // - BufferFlags: 1 byte for each incoming packet buffer; 1=in use, 0=free 1861 //------------------------------------------------------------------------ 1862 realmode = (unsigned char *)Get_RM_IPX_Address(); 1863 realmodelen = Get_RM_IPX_Size(); 1864 size = realmodelen + // assembly routine & its data 1865 (FullPacketLen * NumBufs) + // array of packet buffers 1866 sizeof(ECBType) + // SendECB 1867 FullPacketLen + // SendHeader & SendBuf 1868 NumBufs; // BufferFlags 1869 if (size > 65535) { 1870 return(0); 1871 } 1872 1873 //------------------------------------------------------------------------ 1874 // Allocate DOS memory for the ECB, IPXHeader & packet buffers: 1875 // AX = 0x100 1876 // BX = # paragraphs to allocate 1877 // - if Success, AX = real-mode segment, DX = selector 1878 // - if Failure, carry flag is set 1879 //------------------------------------------------------------------------ 1880 memset (®s, 0 ,sizeof(regs)); 1881 segread (&sregs); 1882 regs.x.eax = DPMI_ALLOC_DOS_MEM; // DPMI function to call 1883 regs.x.ebx = ((size + 15) >> 4); // # paragraphs to allocate 1884 int386x (DPMI_INT, ®s, ®s, &sregs); // allocate the memory 1885 1886 //------------------------------------------------------------------------ 1887 // If the carry flag is set, DPMI is indicating an error. 1888 //------------------------------------------------------------------------ 1889 if (regs.x.cflag) { 1890 return(0); 1891 } 1892 1893 //------------------------------------------------------------------------ 1894 // Save the values of the returned segment & selector 1895 //------------------------------------------------------------------------ 1896 Selector = regs.w.dx; 1897 Segment = regs.w.ax; 1898 RealMemSize = size; 1899 RealModeData = (RealModeDataType *)(((long)Segment) << 4); 1900 1901 //------------------------------------------------------------------------ 1902 // Lock the memory (since we're servicing interrupts with it) 1903 // AX = 0x600 1904 // BX:CX = starting linear address of memory to lock 1905 // SI:DI = size of region to lock (in bytes) 1906 // - If Failure, carry flag is set. 1907 //------------------------------------------------------------------------ 1908 memset (®s, 0 ,sizeof(regs)); 1909 segread (&sregs); 1910 regs.x.eax = DPMI_LOCK_MEM; // DPMI function to call 1911 regs.x.ebx = ((long)RealModeData & 0xffff0000) >> 16; 1912 regs.x.ecx = ((long)RealModeData & 0x0000ffff); 1913 regs.x.esi = ((long)RealMemSize & 0xffff0000) >> 16; 1914 regs.x.edi = ((long)RealMemSize & 0x0000ffff); 1915 int386x (DPMI_INT, ®s, ®s, &sregs); // call DPMI 1916 1917 //------------------------------------------------------------------------ 1918 // If the carry flag is set, DPMI is indicating an error. 1919 //------------------------------------------------------------------------ 1920 if (regs.x.cflag) { 1921 memset (®s, 0 ,sizeof(regs)); 1922 segread (&sregs); 1923 regs.x.eax = DPMI_FREE_DOS_MEM; // DPMI function to call 1924 regs.x.edx = Selector; // ptr to free 1925 int386x (DPMI_INT, ®s, ®s, &sregs); // free the memory 1926 return(0); 1927 } 1928 1929 //------------------------------------------------------------------------ 1930 // Copy the Real-mode code into our memory buffer 1931 //------------------------------------------------------------------------ 1932 p = (char *)(((long)Segment) << 4); 1933 memcpy (p,realmode,realmodelen); 1934 p += realmodelen; 1935 1936 //------------------------------------------------------------------------ 1937 // Compute & save the entry point for the real-mode packet handler 1938 //------------------------------------------------------------------------ 1939 func_val = (unsigned long)RealModeData; 1940 Handler = (((func_val & 0xffff0) << 12) | 1941 ((func_val & 0x000f) + RealModeData->FuncOffset)); 1942 1943 //------------------------------------------------------------------------ 1944 // Fill in buffer pointers 1945 //------------------------------------------------------------------------ 1946 ListenECB = &(RealModeData->ListenECB); 1947 1948 FirstHeaderBuf = (IPXHeaderType *)p; 1949 FirstDataBuf = (((char *)FirstHeaderBuf) + sizeof(IPXHeaderType)); 1950 CurIndex = 0; 1951 CurHeaderBuf = FirstHeaderBuf; 1952 CurDataBuf = FirstDataBuf; 1953 p += FullPacketLen * NumBufs; 1954 1955 SendECB = (ECBType *)p; 1956 p += sizeof (ECBType); 1957 1958 SendHeader = (IPXHeaderType *)p; 1959 p += sizeof (IPXHeaderType); 1960 1961 SendBuf = (char *)p; 1962 p += PacketLen; 1963 1964 BufferFlags = (char *)p; 1965 1966 //------------------------------------------------------------------------ 1967 // Fill in the real-mode routine's data (The ECB will be filled in when we 1968 // command IPX to Listen). 1969 //------------------------------------------------------------------------ 1970 RealModeData->NumBufs = (short)NumBufs; 1971 RealModeData->BufferFlags = (char *) 1972 ((((long)BufferFlags & 0xffff0) << 12) | 1973 ((long)BufferFlags & 0x0000f)); 1974 RealModeData->PacketSize = (short)FullPacketLen; 1975 RealModeData->FirstPacketBuf = (IPXHeaderType *) 1976 ((((long)FirstHeaderBuf & 0xffff0) << 12) | 1977 ((long)FirstHeaderBuf & 0x0000f)); 1978 RealModeData->CurIndex = 0; 1979 RealModeData->CurPacketBuf = RealModeData->FirstPacketBuf; 1980 RealModeData->Semaphore = 0; 1981 RealModeData->ReEntrantCount = 0; 1982 1983 //------------------------------------------------------------------------ 1984 // Init state of all buffers to empty 1985 //------------------------------------------------------------------------ 1986 for (i = 0; i < NumBufs; i++) { 1987 BufferFlags[i] = 0; 1988 } 1989 1990 //------------------------------------------------------------------------ 1991 // Check the start & end markers in the real-mode memory area 1992 //------------------------------------------------------------------------ 1993 if (RealModeData->Marker1 != 0x1111 || 1994 RealModeData->Marker2 != 0x2222) { 1995 Free_RealMode_Mem(); 1996 return(0); 1997 } 1998 else { 1999 return(1); 2000 } 2001 #endif //WIN32 2002 } /* end of Alloc_Realmode_Mem */ 2003 2004 2005 /*************************************************************************** 2006 * IPXManagerClass::Free_RealMode_Mem -- frees real-mode memory * 2007 * * 2008 * INPUT: * 2009 * none. * 2010 * * 2011 * OUTPUT: * 2012 * 1 = OK, 0 = error * 2013 * * 2014 * WARNINGS: * 2015 * none. * 2016 * * 2017 * HISTORY: * 2018 * 12/20/1994 BR : Created. * 2019 *=========================================================================*/ 2020 int IPXManagerClass::Free_RealMode_Mem(void) 2021 { 2022 2023 #ifdef WIN32 2024 2025 return (1); 2026 2027 #else //WIN32 2028 2029 union REGS regs; 2030 struct SREGS sregs; 2031 int rc = 1; 2032 2033 //------------------------------------------------------------------------ 2034 // Unlock the memory 2035 //------------------------------------------------------------------------ 2036 memset (®s, 0 ,sizeof(regs)); 2037 segread (&sregs); 2038 regs.x.eax = DPMI_UNLOCK_MEM; // DPMI function to call 2039 regs.x.ebx = ((long)RealModeData & 0xffff0000) >> 16; 2040 regs.x.ecx = ((long)RealModeData & 0x0000ffff); 2041 regs.x.esi = ((long)RealMemSize & 0xffff0000) >> 16; 2042 regs.x.edi = ((long)RealMemSize & 0x0000ffff); 2043 int386x (DPMI_INT, ®s, ®s, &sregs); // call DPMI 2044 2045 //------------------------------------------------------------------------ 2046 // If the carry flag is set, DPMI is indicating an error. 2047 //------------------------------------------------------------------------ 2048 if (regs.x.cflag) { 2049 rc = 0; 2050 } 2051 2052 //------------------------------------------------------------------------ 2053 // Free DOS memory 2054 //------------------------------------------------------------------------ 2055 memset (®s, 0 ,sizeof(regs)); 2056 segread (&sregs); 2057 regs.x.eax = DPMI_FREE_DOS_MEM; // DPMI function to call 2058 regs.x.edx = Selector; // ptr to free 2059 int386x (DPMI_INT, ®s, ®s, &sregs); // free the memory 2060 2061 return(rc); 2062 #endif //WIN32 2063 2064 } /* end of Free_Realmode_Mem */ 2065 2066 /*************************** end of ipxmgr.cpp *****************************/