IPXCONN.CPP (34946B)
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/IPXCONN.CPP 1 3/03/97 10:24a 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 : IPXCONN.CPP * 24 * * 25 * Programmer : Bill Randolph * 26 * * 27 * Start Date : December 20, 1994 * 28 * * 29 * Last Update : April 9, 1995 [BRR] * 30 * * 31 *-------------------------------------------------------------------------* 32 * Functions: * 33 * IPXConnClass::IPXConnClass -- class constructor * 34 * IPXConnClass::~IPXConnClass -- class destructor * 35 * IPXConnClass::Init -- hardware-specific initialization routine * 36 * IPXConnClass::Configure -- One-time initialization routine * 37 * IPXConnClass::Start_Listening -- commands IPX to listen * 38 * IPXConnClass::Stop_Listening -- commands IPX to stop listen * 39 * IPXConnClass::Send -- sends a packet; invoked by SequencedConnection * 40 * IPXConnClass::Open_Socket -- opens communications socket * 41 * IPXConnClass::Close_Socket -- closes the socket * 42 * IPXConnClass::Send_To -- sends the packet to the given address * 43 * IPXConnClass::Broadcast -- broadcasts the given packet * 44 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 45 46 47 #include "function.h" 48 #include <stdio.h> 49 //#include <mem.h> 50 #include <string.h> 51 #include "ipxconn.h" 52 53 #ifdef WINSOCK_IPX 54 #include "WSProto.h" 55 56 #else 57 58 #include "ipx95.h" 59 #ifdef WIN32 60 #include "tcpip.h" 61 #else //WIN32 62 #include "fakesock.h" 63 #endif //WIN32 64 #endif //WINSOCK_IPX 65 66 67 68 /* 69 ********************************* Globals *********************************** 70 */ 71 unsigned short IPXConnClass::Socket; 72 int IPXConnClass::ConnectionNum; 73 ECBType * IPXConnClass::ListenECB; 74 IPXHeaderType * IPXConnClass::ListenHeader; 75 char * IPXConnClass::ListenBuf; 76 ECBType * IPXConnClass::SendECB; 77 IPXHeaderType * IPXConnClass::SendHeader; 78 char * IPXConnClass::SendBuf; 79 long IPXConnClass::Handler; 80 int IPXConnClass::Configured = 0; 81 int IPXConnClass::SocketOpen = 0; 82 int IPXConnClass::Listening = 0; 83 int IPXConnClass::PacketLen; 84 85 86 /*************************************************************************** 87 * IPXConnClass::IPXConnClass -- class constructor * 88 * * 89 * INPUT: * 90 * numsend desired # of entries for the send queue * 91 * numreceive desired # of entries for the receive queue * 92 * maxlen max length of an application packet * 93 * magicnum the packet "magic number" for this connection * 94 * address address of destination (NULL = no address) * 95 * id connection's unique numerical ID * 96 * name connection's name * 97 * extralen max size of app-specific extra bytes (optional) * 98 * * 99 * OUTPUT: * 100 * none. * 101 * * 102 * WARNINGS: * 103 * none. * 104 * * 105 * HISTORY: * 106 * 12/20/1994 BR : Created. * 107 *=========================================================================*/ 108 IPXConnClass::IPXConnClass (int numsend, int numreceive, int maxlen, 109 unsigned short magicnum, IPXAddressClass *address, int id, char *name, 110 int extralen) : 111 ConnectionClass (numsend, numreceive, maxlen, magicnum, 112 2, // retry delta 113 -1, // max retries 114 60, // timeout 115 extralen) // (currently, this is only used by the Global Channel) 116 { 117 NetNumType net; 118 NetNodeType node; 119 120 /*------------------------------------------------------------------------ 121 Save the values passed in 122 ------------------------------------------------------------------------*/ 123 if (address) 124 Address = (*address); 125 ID = id; 126 strcpy (Name, name); 127 128 #ifdef WINSOCK_IPX 129 Address.Get_Address(net,node); 130 memcpy(ImmediateAddress,node,6); 131 Immed_Set = 0; 132 #else 133 if ( !Winsock.Get_Connected() ) { 134 /*------------------------------------------------------------------------ 135 If our Address field is an actual address (ie NULL wasn't passed to the 136 constructor), pre-compute the ImmediateAddress value for the SendECB. 137 This allows pre-computing of the ImmediateAddress for all connections 138 created after Configure() is called. 139 ------------------------------------------------------------------------*/ 140 if (!Address.Is_Broadcast() && Configured==1) { 141 Address.Get_Address(net,node); 142 143 /*..................................................................... 144 If the user is logged in & has a valid Novell Connection Number, get 145 the bridge address the "official" way 146 .....................................................................*/ 147 if (ConnectionNum != 0) { 148 if (IPX_Get_Local_Target (net, node, Socket, ImmediateAddress)!=0) { 149 memcpy(ImmediateAddress,node,6); 150 } 151 } 152 /*..................................................................... 153 Otherwise, use the destination node address as the ImmediateAddress, 154 and just hope there's no network bridge in the path. 155 .....................................................................*/ 156 else { 157 memcpy(ImmediateAddress,node,6); 158 } 159 160 Immed_Set = 1; 161 } 162 else { 163 memset (ImmediateAddress, 0, 6); 164 Immed_Set = 0; 165 } 166 } 167 #endif //WINSOCK_IPX 168 } /* end of IPXConnClass */ 169 170 171 /*************************************************************************** 172 * IPXConnClass::Init -- hardware-specific initialization routine * 173 * * 174 * INPUT: * 175 * none. * 176 * * 177 * OUTPUT: * 178 * none. * 179 * * 180 * WARNINGS: * 181 * none. * 182 * * 183 * HISTORY: * 184 * 12/20/1994 BR : Created. * 185 *=========================================================================*/ 186 void IPXConnClass::Init (void) 187 { 188 /*------------------------------------------------------------------------ 189 Invoke the parent's Init routine 190 ------------------------------------------------------------------------*/ 191 ConnectionClass::Init(); 192 193 } /* end of Init */ 194 195 196 /*************************************************************************** 197 * IPXConnClass::Configure -- One-time initialization routine * 198 * * 199 * This routine sets up static members that are shared by all IPX * 200 * connections (ie those variables used by the Send/Listen/Broadcast * 201 * routines). * 202 * * 203 * INPUT: * 204 * socket socket ID for sending & receiving * 205 * conn_num local IPX Connection Number (0 = not logged in) * 206 * listen_ecb ptr to ECBType for listening * 207 * send_ecb ptr to ECBType for sending * 208 * listen_header ptr to IPXHeaderType for listening * 209 * send_header ptr to IPXHeaderType for sending * 210 * listen_buf ptr to buffer for listening * 211 * send_buf ptr to buffer for sending * 212 * handler_rm_ptr REAL-MODE pointer to event service routine * 213 * (high word = segment, low word = offset) * 214 * maxpacketlen max packet size to listen for * 215 * * 216 * OUTPUT: * 217 * none. * 218 * * 219 * WARNINGS: * 220 * - All pointers must be protected-mode pointers, but must point to * 221 * DOS real-mode memory (except the Handler segment/offset) * 222 * * 223 * HISTORY: * 224 * 12/20/1994 BR : Created. * 225 *=========================================================================*/ 226 void IPXConnClass::Configure (unsigned short socket, int conn_num, 227 ECBType *listen_ecb, ECBType *send_ecb, IPXHeaderType *listen_header, 228 IPXHeaderType *send_header, char *listen_buf, char *send_buf, 229 long handler_rm_ptr, int maxpacketlen) 230 { 231 /*------------------------------------------------------------------------ 232 Save the values passed in 233 ------------------------------------------------------------------------*/ 234 Socket = socket; 235 ConnectionNum = conn_num; 236 ListenECB = listen_ecb; 237 SendECB = send_ecb; 238 ListenHeader = listen_header; 239 SendHeader = send_header; 240 ListenBuf = listen_buf; 241 SendBuf = send_buf; 242 Handler = handler_rm_ptr; 243 PacketLen = maxpacketlen; 244 245 Configured = 1; 246 247 } /* end of Configure */ 248 249 250 /*************************************************************************** 251 * IPXConnClass::Start_Listening -- commands IPX to listen * 252 * * 253 * This routine may be used to start listening in polled mode (if the * 254 * ECB's Event_Service_Routine is NULL), or in interrupt mode; it's * 255 * up to the caller to fill the ECB in. If in polled mode, Listening * 256 * must be restarted every time a packet comes in. * 257 * * 258 * INPUT: * 259 * none. * 260 * * 261 * OUTPUT: * 262 * none. * 263 * * 264 * WARNINGS: * 265 * - The ListenECB must have been properly filled in by the IPX Manager.* 266 * - Configure must be called before calling this routine. * 267 * * 268 * HISTORY: * 269 * 12/16/1994 BR : Created. * 270 *=========================================================================*/ 271 int IPXConnClass::Start_Listening(void) 272 { 273 #ifdef WIN32 274 275 #ifdef WINSOCK_IPX 276 /* 277 ** Open the socket. 278 */ 279 if (!Open_Socket(Socket)) 280 return(false); 281 282 /* 283 ** start listening on the socket. 284 */ 285 if ( PacketTransport->Start_Listening () ) { 286 Listening =1; 287 return (true); 288 } else { 289 Close_Socket(Socket); 290 return (false); 291 } 292 293 #else 294 if (Winsock.Get_Connected ()) return (true); 295 296 /*------------------------------------------------------------------------ 297 Open the Socket 298 ------------------------------------------------------------------------*/ 299 if (!Open_Socket(Socket)) 300 return(false); 301 302 if (IPX_Start_Listening95()) { 303 Listening =1; 304 return (true); 305 } else { 306 Close_Socket(Socket); 307 return (false); 308 } 309 #endif //WINSOCK_IPX 310 311 #else //WIN32 312 313 void *hdr_ptr; 314 unsigned long hdr_val; 315 void *buf_ptr; 316 unsigned long buf_val; 317 int rc; 318 319 /*------------------------------------------------------------------------ 320 Don't do a thing unless we've been configured, and we're not listening. 321 ------------------------------------------------------------------------*/ 322 if (Configured==0 || Listening==1) { 323 return(0); 324 } 325 326 /*------------------------------------------------------------------------ 327 Open the Socket 328 ------------------------------------------------------------------------*/ 329 if (!Open_Socket(Socket)) { 330 return(0); 331 } 332 333 /*------------------------------------------------------------------------ 334 Clear the ECB & header 335 ------------------------------------------------------------------------*/ 336 memset(ListenECB, 0, sizeof(ECBType)); 337 memset(ListenHeader, 0, sizeof(IPXHeaderType)); 338 339 /*------------------------------------------------------------------------ 340 Convert protected-mode ptrs to real-mode ptrs 341 ------------------------------------------------------------------------*/ 342 hdr_val = (unsigned long)ListenHeader; 343 hdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f)); 344 345 buf_val = (unsigned long)ListenBuf; 346 buf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f)); 347 348 /*------------------------------------------------------------------------ 349 Fill in the ECB 350 ------------------------------------------------------------------------*/ 351 ListenECB->SocketNumber = Socket; 352 ListenECB->PacketCount = 2; 353 ListenECB->Packet[0].Address = hdr_ptr; 354 ListenECB->Packet[0].Length = sizeof(IPXHeaderType); 355 ListenECB->Packet[1].Address = buf_ptr; 356 ListenECB->Packet[1].Length = (unsigned short)PacketLen; 357 358 ((long &)ListenECB->Event_Service_Routine) = Handler; 359 360 /*------------------------------------------------------------------------ 361 Command IPX to listen 362 ------------------------------------------------------------------------*/ 363 rc = IPX_Listen_For_Packet(ListenECB); 364 if (rc!=0) { 365 Close_Socket(Socket); 366 return(0); 367 } 368 else { 369 Listening = 1; 370 return(1); 371 } 372 373 #endif //WIN32 374 375 } /* end of Start_Listening */ 376 377 378 /*************************************************************************** 379 * IPXConnClass::Stop_Listening -- commands IPX to stop listen * 380 * * 381 * INPUT: * 382 * none. * 383 * * 384 * OUTPUT: * 385 * none. * 386 * * 387 * WARNINGS: * 388 * - This routine MUST NOT be called if IPX is not listening already! * 389 * * 390 * HISTORY: * 391 * 12/16/1994 BR : Created. * 392 *=========================================================================*/ 393 int IPXConnClass::Stop_Listening(void) 394 { 395 #ifdef WINSOCK_IPX 396 if ( PacketTransport ) PacketTransport->Stop_Listening(); 397 Listening = 0; 398 399 // All done. 400 return(1); 401 #else 402 /*------------------------------------------------------------------------ 403 Don't do anything unless we're already Listening. 404 ------------------------------------------------------------------------*/ 405 if (Listening==0) { 406 return(0); 407 } 408 409 #ifdef WIN32 410 411 if (Winsock.Get_Connected()) { 412 Listening = 0; 413 return (true); 414 } else { 415 IPX_Shut_Down95(); 416 Close_Socket(Socket); 417 } 418 419 #else //WIN32 420 421 /*------------------------------------------------------------------------ 422 Shut IPX down. 423 ------------------------------------------------------------------------*/ 424 IPX_Cancel_Event(ListenECB); 425 Close_Socket(Socket); 426 427 #endif //WIN32 428 429 Listening = 0; 430 431 /*------------------------------------------------------------------------ 432 All done. 433 ------------------------------------------------------------------------*/ 434 return(1); 435 #endif //WINSOCK_IPX 436 437 } /* end of Stop_Listening */ 438 439 440 /*************************************************************************** 441 * IPXConnClass::Send -- sends a packet; invoked by SequencedConnection * 442 * * 443 * INPUT: * 444 * buf buffer to send * 445 * buflen length of buffer to send * 446 * extrabuf (not used by this class) * 447 * extralen (not used by this class) * 448 * * 449 * OUTPUT: * 450 * 1 = OK, 0 = error * 451 * * 452 * WARNINGS: * 453 * none. * 454 * * 455 * HISTORY: * 456 * 12/16/1994 BR : Created. * 457 *=========================================================================*/ 458 int IPXConnClass::Send(char *buf, int buflen, void *, int) 459 { 460 /*------------------------------------------------------------------------ 461 Invoke our own Send_To routine, filling in our Address as the destination. 462 ------------------------------------------------------------------------*/ 463 if (Immed_Set) { 464 return(Send_To (buf, buflen, &Address, ImmediateAddress)); 465 } 466 else { 467 return(Send_To (buf, buflen, &Address, NULL)); 468 } 469 470 } /* end of Send */ 471 472 473 /*************************************************************************** 474 * IPXConnClass::Open_Socket -- opens communications socket * 475 * * 476 * INPUT: * 477 * socket desired socket ID number * 478 * * 479 * OUTPUT: * 480 * 1 = OK, 0 = error * 481 * * 482 * WARNINGS: * 483 * none. * 484 * * 485 * HISTORY: * 486 * 12/16/1994 BR : Created. * 487 *=========================================================================*/ 488 int IPXConnClass::Open_Socket(unsigned short socket) 489 { 490 int rc; 491 #ifdef WINSOCK_IPX 492 rc = PacketTransport->Open_Socket(socket); 493 494 SocketOpen = rc; 495 return ( rc ); 496 497 #else //WINSOCK_IPX 498 if (Winsock.Get_Connected()) { 499 SocketOpen = 1; 500 return (true); 501 } 502 503 SocketOpen = 0; 504 505 /*------------------------------------------------------------------------ 506 Try to open a listen socket. The socket may have been left open by 507 a previously-crashed program, so ignore the state of the SocketOpen 508 flag for this call; use IPX to determine if the socket was already open. 509 ------------------------------------------------------------------------*/ 510 rc = IPX_Open_Socket(socket); 511 if (rc) { 512 513 /*..................................................................... 514 If already open, close & reopen it 515 .....................................................................*/ 516 if (rc==IPXERR_SOCKET_ERROR) { 517 #ifdef WIN32 518 WWDebugString ("Error -- Specified socket is already open"); 519 #endif //WIN32 520 IPX_Close_Socket(socket); 521 rc = IPX_Open_Socket(socket); 522 } 523 524 /*.................................................................. 525 Still can't open: return error 526 ..................................................................*/ 527 if (rc) { 528 return(0); 529 } 530 } 531 532 SocketOpen = 1; 533 534 return(1); 535 #endif //WINSOCK_IPX 536 537 } /* end of Open_Socket */ 538 539 540 /*************************************************************************** 541 * IPXConnClass::Close_Socket -- closes the socket * 542 * * 543 * INPUT: * 544 * socket desired socket ID number * 545 * * 546 * OUTPUT: * 547 * none. * 548 * * 549 * WARNINGS: * 550 * Calling this routine when the sockets aren't open may crash! * 551 * * 552 * HISTORY: * 553 * 12/16/1994 BR : Created. * 554 *=========================================================================*/ 555 void IPXConnClass::Close_Socket(unsigned short socket) 556 { 557 #ifdef WINSOCK_IPX 558 socket = socket; 559 PacketTransport->Close_Socket(); 560 SocketOpen = 0; 561 #else //WINSOCK_IPX 562 if (Winsock.Get_Connected()) { 563 SocketOpen = 0; 564 return; 565 } 566 567 /*------------------------------------------------------------------------ 568 Never, ever, ever, under any circumstances whatsoever, close a socket 569 that isn't open. You'll regret it forever (or until at least until 570 you're through rebooting, which, if you're on a Pentium is the same 571 thing). 572 ------------------------------------------------------------------------*/ 573 if (SocketOpen==1) { 574 IPX_Close_Socket(socket); 575 } 576 577 SocketOpen = 0; 578 #endif //WINSOCK_IPX 579 } /* end of Close_Socket */ 580 581 582 /*************************************************************************** 583 * IPXConnClass::Send_To -- sends the packet to the given address * 584 * * 585 * The "ImmediateAddress" field of the SendECB must be filled in with the * 586 * address of a bridge, or the node address of the destination if there * 587 * is no bridge. The NETX call to find this address will always crash * 588 * if NETX isn't loaded (ConnectionNum is 0), so this case is trapped & * 589 * prevented. * 590 * Also, if the address of this IPX connection is known when the * 591 * constructor is called, and Configure has been called, Get_Local_Target * 592 * is called to precompute the ImmediateAddress; this case is detected & * 593 * if the value is already computed, it's just memcpy'd over. * 594 * * 595 * INPUT: * 596 * buf buffer to send * 597 * buflen length of buffer * 598 * address Address to send to * 599 * immed ImmediateAddress value, NULL if none * 600 * * 601 * OUTPUT: * 602 * 1 = OK, 0 = error * 603 * * 604 * WARNINGS: * 605 * none. * 606 * * 607 * HISTORY: * 608 * 12/16/1994 BR : Created. * 609 *=========================================================================*/ 610 int IPXConnClass::Send_To(char *buf, int buflen, IPXAddressClass *address, 611 NetNodeType immed) 612 { 613 #ifdef WINSOCK_IPX 614 615 immed = immed; 616 assert ( immed == NULL ); 617 PacketTransport->WriteTo ( (void*)buf, buflen, (void*) address ); 618 return (true); 619 620 #else //WINSOCK_IPX 621 NetNumType net; 622 NetNodeType node; 623 int rc; 624 625 #ifdef WIN32 626 627 unsigned char send_address[6]; 628 629 if (Winsock.Get_Connected()) { 630 Winsock.Write((void*)buf, buflen); 631 return (true); 632 } 633 634 if (immed) { 635 memcpy(send_address, immed, 6); 636 #ifdef FIXIT_DESTNET 637 // fixes DESTNET 638 address->Get_Address(net,node); 639 #else 640 // breaks DESTNET 641 memcpy(node, immed, 6); 642 memset (net, 0, sizeof(net) ); 643 #endif 644 } else { 645 address->Get_Address(net,node); 646 /*..................................................................... 647 If the user is logged in & has a valid Novell Connection Number, get the 648 bridge address the "official" way 649 .....................................................................*/ 650 if (ConnectionNum != 0) { 651 rc = IPX_Get_Local_Target (net, node, Socket, &send_address[0]); 652 if (rc!=0) { 653 return(false); 654 } 655 } else { 656 /*..................................................................... 657 Otherwise, use the destination node address as the ImmediateAddress, and 658 just hope there's no network bridge in the path. 659 .....................................................................*/ 660 memcpy(send_address,node,6); 661 } 662 } 663 664 return (IPX_Send_Packet95(&send_address[0], (unsigned char*)buf, buflen, (unsigned char*)net, (unsigned char*)node)); 665 666 #else //WIN32 667 668 void *hdr_ptr; 669 void *buf_ptr; 670 unsigned long hdr_val; 671 unsigned long buf_val; 672 673 /*------------------------------------------------------------------------ 674 Clear the ECB & header 675 ------------------------------------------------------------------------*/ 676 memset(SendECB, 0, sizeof(ECBType)); 677 memset(SendHeader, 0, sizeof(IPXHeaderType)); 678 679 /*------------------------------------------------------------------------ 680 Copy the message into the SendBuf 681 ------------------------------------------------------------------------*/ 682 memcpy (SendBuf,buf,buflen); 683 684 /*------------------------------------------------------------------------ 685 Convert protected-mode ptrs to real-mode ptrs 686 ------------------------------------------------------------------------*/ 687 hdr_val = (unsigned long)SendHeader; 688 hdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f)); 689 buf_val = (unsigned long)SendBuf; 690 buf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f)); 691 692 /*------------------------------------------------------------------------ 693 Fill in ECB 694 ------------------------------------------------------------------------*/ 695 SendECB->SocketNumber = Socket; // my output socket 696 SendECB->PacketCount = 2; // 2 data areas 697 SendECB->Packet[0].Address = hdr_ptr; 698 SendECB->Packet[0].Length = sizeof(IPXHeaderType); 699 SendECB->Packet[1].Address = buf_ptr; 700 SendECB->Packet[1].Length = (unsigned short)buflen; 701 702 /*------------------------------------------------------------------------ 703 Get the bridge address 704 ------------------------------------------------------------------------*/ 705 if (immed) { 706 memcpy(SendECB->ImmediateAddress, immed, 6); 707 } 708 else { 709 address->Get_Address(net,node); 710 711 /*..................................................................... 712 If the user is logged in & has a valid Novell Connection Number, get 713 the bridge address the "official" way 714 .....................................................................*/ 715 if (ConnectionNum != 0) { 716 rc = IPX_Get_Local_Target (net, node, Socket, 717 SendECB->ImmediateAddress); 718 if (rc!=0) { 719 return(0); 720 } 721 } 722 /*..................................................................... 723 Otherwise, use the destination node address as the ImmediateAddress, 724 and just hope there's no network bridge in the path. 725 .....................................................................*/ 726 else { 727 memcpy(SendECB->ImmediateAddress,node,6); 728 } 729 } 730 731 /*------------------------------------------------------------------------ 732 Fill in outgoing header 733 ------------------------------------------------------------------------*/ 734 SendHeader->PacketType = 4; // 4 = IPX packet 735 address->Get_Address(SendHeader); // fill in header addresses 736 SendHeader->DestNetworkSocket = Socket; // destination socket id 737 738 /*------------------------------------------------------------------------ 739 Send the packet 740 ------------------------------------------------------------------------*/ 741 IPX_Send_Packet(SendECB); 742 743 /*------------------------------------------------------------------------ 744 Wait for send to complete 745 ------------------------------------------------------------------------*/ 746 while (SendECB->InUse) 747 Let_IPX_Breath(); 748 749 if (SendECB->CompletionCode!=0) { 750 return(0); 751 } 752 else { 753 return(1); 754 } 755 756 #endif //WIN32 757 #endif //WINSOCK_IPX 758 759 } /* end of Send_To */ 760 761 762 /*************************************************************************** 763 * IPXConnClass::Broadcast -- broadcasts the given packet * 764 * * 765 * INPUT: * 766 * socket desired socket ID number * 767 * * 768 * OUTPUT: * 769 * 1 = OK, 0 = error * 770 * * 771 * WARNINGS: * 772 * none. * 773 * * 774 * HISTORY: * 775 * 12/16/1994 BR : Created. * 776 *=========================================================================*/ 777 int IPXConnClass::Broadcast(char *buf, int buflen) 778 { 779 #ifdef WINSOCK_IPX 780 PacketTransport->Broadcast (buf, buflen); 781 return (true); 782 783 #else //WINSOCK_IPX 784 785 #ifdef WIN32 786 787 if (Winsock.Get_Connected()) { 788 Winsock.Write((void*)buf, buflen); 789 return(true); 790 } else { 791 return (IPX_Broadcast_Packet95((unsigned char*)buf, buflen)); 792 } 793 794 #else //WIN32 795 796 void *hdr_ptr; 797 void *buf_ptr; 798 unsigned long hdr_val; 799 unsigned long buf_val; 800 801 /*------------------------------------------------------------------------ 802 Clear the ECB & header 803 ------------------------------------------------------------------------*/ 804 memset(SendECB, 0, sizeof(ECBType)); 805 memset(SendHeader, 0, sizeof(IPXHeaderType)); 806 807 /*------------------------------------------------------------------------ 808 Copy the message into the SendBuf 809 ------------------------------------------------------------------------*/ 810 memcpy (SendBuf,buf,buflen); 811 812 /*------------------------------------------------------------------------ 813 Convert protected-mode ptrs to real-mode ptrs 814 ------------------------------------------------------------------------*/ 815 hdr_val = (unsigned long)SendHeader; 816 hdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f)); 817 buf_val = (unsigned long)SendBuf; 818 buf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f)); 819 820 /*------------------------------------------------------------------------ 821 Fill in ECB 822 ------------------------------------------------------------------------*/ 823 SendECB->SocketNumber = Socket; // my output socket 824 SendECB->PacketCount = 2; // 2 data areas 825 SendECB->Packet[0].Address = hdr_ptr; 826 SendECB->Packet[0].Length = sizeof(IPXHeaderType); 827 SendECB->Packet[1].Address = buf_ptr; 828 SendECB->Packet[1].Length = (unsigned short)buflen; 829 SendECB->ImmediateAddress[0] = 0xff; 830 SendECB->ImmediateAddress[1] = 0xff; 831 SendECB->ImmediateAddress[2] = 0xff; 832 SendECB->ImmediateAddress[3] = 0xff; 833 SendECB->ImmediateAddress[4] = 0xff; 834 SendECB->ImmediateAddress[5] = 0xff; 835 836 /*------------------------------------------------------------------------ 837 Fill in outgoing header 838 ------------------------------------------------------------------------*/ 839 SendHeader->PacketType = 4; // 4 = IPX packet 840 SendHeader->DestNetworkNumber[0] = 0xff; // 0xff = broadcast 841 SendHeader->DestNetworkNumber[1] = 0xff; 842 SendHeader->DestNetworkNumber[2] = 0xff; 843 SendHeader->DestNetworkNumber[3] = 0xff; 844 SendHeader->DestNetworkNode[0] = 0xff; // 0xff = broadcast 845 SendHeader->DestNetworkNode[1] = 0xff; 846 SendHeader->DestNetworkNode[2] = 0xff; 847 SendHeader->DestNetworkNode[3] = 0xff; 848 SendHeader->DestNetworkNode[4] = 0xff; 849 SendHeader->DestNetworkNode[5] = 0xff; 850 SendHeader->DestNetworkSocket = Socket; // destination socket # 851 852 /*------------------------------------------------------------------------ 853 Send the packet 854 ------------------------------------------------------------------------*/ 855 IPX_Send_Packet(SendECB); 856 857 /*------------------------------------------------------------------------ 858 Wait for send to complete 859 ------------------------------------------------------------------------*/ 860 while (SendECB->InUse) { 861 Let_IPX_Breath(); 862 } 863 864 if (SendECB->CompletionCode!=0) { 865 return(0); 866 } 867 else { 868 return(1); 869 } 870 871 #endif //WIN32 872 #endif //WINSOCK_IPX 873 } /* end of Broadcast */ 874 875 /************************** end of ipxconn.cpp *****************************/ 876