IPXCONN.CPP 34 KB

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