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