IPXCONN.CPP 34 KB

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