socket.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. // socket.h
  19. // Project: Postal
  20. //
  21. // History:
  22. // 02/19/97 MJR Started.
  23. //
  24. // 04/08/97 MJR Added class and function names to all TRACE() messages.
  25. //
  26. // Added test for minimum number of sockets supported.
  27. //
  28. // Fixed problem that would have occurred if an error occurred
  29. // when removing the blocking hook.
  30. //
  31. // 04/12/97 MJR Distilled this file out of what was gamelink.cpp in order
  32. // to separate the socket stuff from the game stuff.
  33. //
  34. // Major changes to create a simplified, generic,
  35. // socket-oriented interface.
  36. //
  37. // 04/13/97 MJR Continued a huge number of changes, including many of
  38. // the outstanding issues that had been listed in the
  39. // comment header of the previous incarnation of this file.
  40. //
  41. // 04/14/97 MJR Lots of testing, debugging, fixing, etc.
  42. //
  43. // 05/20/97 MJR Minor changes.
  44. //
  45. // 05/21/97 MJR Pulled "listen" option out of Open() and made it a
  46. // separate function.
  47. //
  48. // Created two Open() variations, one for datagrams and one
  49. // for streams, each with separate options.
  50. //
  51. // 05/23/97 MJR Renamed parameters to GetAddress().
  52. //
  53. // 05/25/97 MJR Changed type in Address from int (iLen) to long (lLen).
  54. //
  55. // 05/25/97 MJR Added ability to set callback via Open().
  56. //
  57. // 05/26/97 MJR Changed IsError() so it no longer considers a closed
  58. // socket to be an error.
  59. //
  60. // 08/03/97 BRH Added IPX network support.
  61. //
  62. // 08/04/97 BRH Restarted this file to use the new plugin protocols
  63. //
  64. // 08/08/97 MJR Another round of cleanups, and added support for
  65. // handling Win32 -vs- Mac protocols.
  66. //
  67. // 08/09/97 MJR Added broadcast support.
  68. // Added check to be sure all addresses are the same size.
  69. //
  70. // 08/12/97 MJR Added mac protocols.
  71. //
  72. // 08/18/97 MJR Now trims leading and trailing whitespace from names.
  73. // MJR Tweaked for mac.
  74. //
  75. // 08/20/97 MJR Added support for setting whether socket blocks or not.
  76. //
  77. // 11/19/97 JMI Added "MPATH" string for corresponding MPATH enum in
  78. // socket.h. Since there was no string for this protocol,
  79. // when toggling through the various protocols in the
  80. // multiplayer options menu, you would get random varing
  81. // strings for the 3rd protocol (MPATH).
  82. //
  83. ////////////////////////////////////////////////////////////////////////////////
  84. #include <ctype.h>
  85. #include "RSPiX.h"
  86. #include "socket.h"
  87. ////////////////////////////////////////////////////////////////////////////////
  88. // Macros
  89. ////////////////////////////////////////////////////////////////////////////////
  90. ////////////////////////////////////////////////////////////////////////////////
  91. // RSocket static member variables
  92. ////////////////////////////////////////////////////////////////////////////////
  93. bool RSocket::ms_bDidStartup = false;
  94. bool RSocket::ms_bAutoShutdown = false;
  95. RSocket::ProtoType RSocket::ms_prototype = RSocket::NO_PROTOCOL;
  96. short RSocket::ms_sNumSockets = 0;
  97. char* RSocket::ms_apszProtoNames[] =
  98. {
  99. "",
  100. // "Loopback",
  101. "TCP/IP",
  102. };
  103. ////////////////////////////////////////////////////////////////////////////////
  104. // RProtocol static member variables
  105. ////////////////////////////////////////////////////////////////////////////////
  106. RSocket::ProtoType RSocket::RProtocol::ms_prototype = RSocket::NO_PROTOCOL;
  107. ////////////////////////////////////////////////////////////////////////////////
  108. // Constructor
  109. ////////////////////////////////////////////////////////////////////////////////
  110. RSocket::RSocket()
  111. {
  112. m_pProtocol = 0;
  113. // Update number of sockets
  114. ms_sNumSockets++;
  115. }
  116. ////////////////////////////////////////////////////////////////////////////////
  117. // Destructor
  118. ////////////////////////////////////////////////////////////////////////////////
  119. RSocket::~RSocket()
  120. {
  121. Reset();
  122. // Update number of sockets
  123. ms_sNumSockets--;
  124. // If there's no more sockets and auto-shutdown is enabled, then shtudown
  125. if ((ms_sNumSockets == 0) && ms_bAutoShutdown)
  126. Shutdown();
  127. }
  128. ////////////////////////////////////////////////////////////////////////////////
  129. // Reset socket to its post-construction state
  130. ////////////////////////////////////////////////////////////////////////////////
  131. void RSocket::Reset(void)
  132. {
  133. // Force it to close now
  134. Close(true);
  135. // If close failed, we're going to delete protocol anyway as part of reset
  136. delete m_pProtocol;
  137. m_pProtocol = NULL;
  138. }
  139. ////////////////////////////////////////////////////////////////////////////////
  140. // Open socket
  141. //
  142. // If the current protocol is not supported, this function returns the value
  143. // RSocket::errNotSupported.
  144. ////////////////////////////////////////////////////////////////////////////////
  145. short RSocket::Open( // Returns 0 on success, non-zero otherwise
  146. unsigned short usPort, // In: Port number or 0 for any port
  147. short sType, // In: Any one RSocket::typ* enum
  148. short sOptionFlags, // In: Any combo of RSocket::opt* enums
  149. RSocket::BLOCK_CALLBACK callback) // In: Blocking callback (or NULL to keep current)
  150. {
  151. // Make sure startup was called. Only this function needs to do this
  152. // because all the others check for a valid protocol, which can only be
  153. // created via this function.
  154. short sResult = 0;
  155. if (ms_bDidStartup)
  156. {
  157. // Make sure socket isn't already open
  158. if (m_pProtocol == NULL)
  159. {
  160. // Note that we create the protocol object here instead of when this
  161. // socket was itself constructed. This is preferable because users might
  162. // want to create a static RSocket object, which would occur before the
  163. // protocol has been set via RSocket::Startup, and therefore wouldn't be
  164. // able to know what type of protocol object to create. By deferring the
  165. // creation of the protocol to this point, we allow for the use of static
  166. // RSocket objects.
  167. m_pProtocol = ConstructProtocol(ms_prototype);
  168. if (m_pProtocol != NULL)
  169. {
  170. sResult = m_pProtocol->Open(usPort, sType, sOptionFlags, callback);
  171. }
  172. else
  173. {
  174. sResult = -1;
  175. TRACE("RSocket::Open(): Error constructing protocol!\n");
  176. }
  177. // If there was a problem, get rid of the protocol
  178. if (sResult != 0)
  179. {
  180. delete m_pProtocol;
  181. m_pProtocol = 0;
  182. }
  183. }
  184. else
  185. {
  186. sResult = -1;
  187. TRACE("RSocket::Open(): Already open!\n");
  188. }
  189. }
  190. else
  191. {
  192. sResult = -1;
  193. TRACE("RSocket::Open(): Didn't call RSocket::Startup()!\n");
  194. }
  195. return sResult;
  196. }
  197. ////////////////////////////////////////////////////////////////////////////////
  198. // Close socket
  199. ////////////////////////////////////////////////////////////////////////////////
  200. short RSocket::Close( // Returns 0 if successfull, non-zero otherwise
  201. bool bForceNow /*= true */) // In: 'true' means do it now, false follows normal rules
  202. {
  203. short sResult = 0;
  204. if (m_pProtocol != NULL)
  205. {
  206. // Close socket
  207. sResult = m_pProtocol->Close(bForceNow);
  208. if (sResult == 0)
  209. {
  210. // Get rid of protocol
  211. delete m_pProtocol;
  212. m_pProtocol = NULL;
  213. }
  214. }
  215. return sResult;
  216. }
  217. ////////////////////////////////////////////////////////////////////////////////
  218. // Accept request for connection.
  219. //
  220. // If this function fails, the specified client socket and address may have
  221. // been modified, but any such changes must not be relied upon!!! What can be
  222. // relied upon is that the client socket will be in a "closed" state.
  223. ////////////////////////////////////////////////////////////////////////////////
  224. short RSocket::Accept( // Return 0 if successfull, non-zero otherwise
  225. RSocket* psocketClient, // Out: Client socket returned here
  226. RSocket::Address* paddressClient) const // Out: Client's address returned here
  227. {
  228. short sResult = FAILURE;
  229. if (m_pProtocol != NULL)
  230. {
  231. // Make sure client doesn't already have a protocol
  232. if (psocketClient->m_pProtocol == 0)
  233. {
  234. // Create protocol
  235. psocketClient->m_pProtocol = ConstructProtocol(ms_prototype);
  236. if (psocketClient->m_pProtocol != NULL)
  237. {
  238. sResult = m_pProtocol->Accept(psocketClient->m_pProtocol, paddressClient);
  239. // If there was a problem, get rid of the protocol
  240. if (sResult != 0)
  241. {
  242. // Get rid of protocol
  243. delete psocketClient->m_pProtocol;
  244. psocketClient->m_pProtocol = 0;
  245. }
  246. }
  247. else
  248. {
  249. sResult = -1;
  250. TRACE("RSocket::Accept(): Couldn't construct client protocol!\n");
  251. }
  252. }
  253. else
  254. {
  255. sResult = -1;
  256. TRACE("RSocket::Accept(): Client socket already has a protocol!\n");
  257. }
  258. }
  259. else
  260. {
  261. sResult = -1;
  262. TRACE("RSocket::Accept(): Not open!\n");
  263. }
  264. return sResult;
  265. }
  266. ////////////////////////////////////////////////////////////////////////////////
  267. // Set socket to broadcast mode
  268. //
  269. // Most protocols only allow broadcasting on a datagram-style socket.
  270. ////////////////////////////////////////////////////////////////////////////////
  271. short RSocket::Broadcast(void) // Returns 0 if successfull, non-zero otherwise
  272. {
  273. short sResult = FAILURE;
  274. if (m_pProtocol != NULL)
  275. sResult = m_pProtocol->Broadcast();
  276. else
  277. {
  278. sResult = -1;
  279. TRACE("RSocket::Broadcast(): Not open!\n");
  280. }
  281. return sResult;
  282. }
  283. ////////////////////////////////////////////////////////////////////////////////
  284. // Set socket to listen for connection requests
  285. ////////////////////////////////////////////////////////////////////////////////
  286. short RSocket::Listen(short sMaxQueued)
  287. {
  288. short sResult = FAILURE;
  289. if (m_pProtocol != NULL)
  290. sResult = m_pProtocol->Listen(sMaxQueued);
  291. else
  292. {
  293. sResult = -1;
  294. TRACE("RSocket::Listen(): Not open!\n");
  295. }
  296. return sResult;
  297. }
  298. ////////////////////////////////////////////////////////////////////////////////
  299. // Connect to address
  300. ////////////////////////////////////////////////////////////////////////////////
  301. short RSocket::Connect(
  302. RSocket::Address* paddress)
  303. {
  304. short sResult = 0;
  305. if (m_pProtocol != NULL)
  306. sResult = m_pProtocol->Connect(paddress);
  307. else
  308. {
  309. sResult = -1;
  310. TRACE("RSocket::Connect(): Not open!\n");
  311. }
  312. return sResult;
  313. }
  314. ////////////////////////////////////////////////////////////////////////////////
  315. // Use Send for connected sockets - use SendTo for connectionless
  316. ////////////////////////////////////////////////////////////////////////////////
  317. short RSocket::Send( // Return 0 on success, non-zero otherwise
  318. void* pBuf, // In: Pointer to data buffer
  319. long lNumBytes, // In: Number of bytes to send
  320. long* plActualBytes) // Out: Actual number of bytes sent
  321. {
  322. short sResult = FAILURE;
  323. if (m_pProtocol != NULL)
  324. sResult = m_pProtocol->Send(pBuf, lNumBytes, plActualBytes);
  325. else
  326. {
  327. sResult = -1;
  328. TRACE("RSocket::Send(): Not open!\n");
  329. }
  330. return sResult;
  331. }
  332. ////////////////////////////////////////////////////////////////////////////////
  333. // Send data to specified address. For connected sockets, address is ignored
  334. // See Send() for more information.
  335. ////////////////////////////////////////////////////////////////////////////////
  336. short RSocket::SendTo( // Return 0 on success, non-zero otherwise
  337. void* pBuf, // In: Pointer to data buffer
  338. long lNumBytes, // In: Number of bytes to send
  339. long* plActualBytes, // Out: Actual number of bytes sent
  340. RSocket::Address* paddress) //In: Address to send to
  341. {
  342. short sResult = FAILURE;
  343. if (m_pProtocol != NULL)
  344. sResult = m_pProtocol->SendTo(pBuf, lNumBytes, plActualBytes, paddress);
  345. else
  346. {
  347. sResult = -1;
  348. TRACE("RSocket::SendTo(): Not open!\n");
  349. }
  350. return sResult;
  351. }
  352. ////////////////////////////////////////////////////////////////////////////////
  353. // Receive data (only valid for connected sockets -- see also ReceiveFrom())
  354. //
  355. // For datagram (UDP) sockets, there is a one-to-one correspondence between
  356. // sends and receives. Each send implies a matching receive. The specified
  357. // buffer must at least as large as the amount of data that was sent, or the
  358. // data will be truncated and an error will be returned.
  359. //
  360. // For stream (TCP) sockets, there is no direct correspondence between sends
  361. // and receive. One send can be broken up and require multiple receives, and
  362. // and multiple sends can be coalesced into a single recieve. There is no
  363. // limitation on the amount of data being received.
  364. //
  365. // For stream (TCP) sockets, if the actual number of bytes received is 0, it
  366. // means the other end disconnected gracefully.
  367. //
  368. // In all cases, if the connection was abortively disconnected, an error will
  369. // be returned.
  370. ////////////////////////////////////////////////////////////////////////////////
  371. short RSocket::Receive( // Returns 0 on success, non-zero otherwise
  372. void* pBuf, // In: Pointer to data buffer
  373. long lMaxBytes, // In: Maximum bytes that can fit in buffer
  374. long* plActualBytes) // Out: Actual number of bytes received
  375. {
  376. short sResult = FAILURE;
  377. if (m_pProtocol != NULL)
  378. sResult = m_pProtocol->Receive(pBuf, lMaxBytes, plActualBytes);
  379. else
  380. {
  381. sResult = -1;
  382. TRACE("RSocket::Receive(): Not open!\n");
  383. }
  384. return sResult;
  385. }
  386. ////////////////////////////////////////////////////////////////////////////////
  387. // Receive data and get source address
  388. ////////////////////////////////////////////////////////////////////////////////
  389. short RSocket::ReceiveFrom( // Returns 0 on success, non-zero otherwise
  390. void* pBuf, // In: Pointer to data buffer
  391. long lMaxBytes, // In: Maxiumm bytes that fit in buffer
  392. long* plActualBytes, // Out: Actual number of bytes received into buffer
  393. RSocket::Address* paddress) // Out: Source address returned here
  394. {
  395. short sResult = FAILURE;
  396. if (m_pProtocol != NULL)
  397. sResult = m_pProtocol->ReceiveFrom(pBuf, lMaxBytes, plActualBytes, paddress);
  398. else
  399. {
  400. sResult = -1;
  401. TRACE("RSocket::ReceiveFrom(): Not open!\n");
  402. }
  403. return sResult;
  404. }
  405. ////////////////////////////////////////////////////////////////////////////////
  406. // Check the number of bytes of data receivable without blocking.
  407. // For datagrams, this returns the size of the next queued datagram. For
  408. // streams, this returns the total amount of data that can be read with a
  409. // single receive which is normally equal to the total amount of queued data.
  410. ////////////////////////////////////////////////////////////////////////////////
  411. long RSocket::CheckReceivableBytes(void)
  412. {
  413. long lResult = 0;
  414. if (m_pProtocol != NULL)
  415. lResult = m_pProtocol->CheckReceivableBytes();
  416. return lResult;
  417. }
  418. ////////////////////////////////////////////////////////////////////////////////
  419. // CanAcceptWithoutBlocking
  420. ////////////////////////////////////////////////////////////////////////////////
  421. bool RSocket::CanAcceptWithoutBlocking(void)
  422. {
  423. bool bNoBlock = false;
  424. if (m_pProtocol != NULL)
  425. bNoBlock = m_pProtocol->CanAcceptWithoutBlocking();
  426. return bNoBlock;
  427. }
  428. ////////////////////////////////////////////////////////////////////////////////
  429. // CanSendWithoutBlocking
  430. ////////////////////////////////////////////////////////////////////////////////
  431. bool RSocket::CanSendWithoutBlocking(void)
  432. {
  433. bool bNoBlock = false;
  434. if (m_pProtocol != NULL)
  435. bNoBlock = m_pProtocol->CanSendWithoutBlocking();
  436. return bNoBlock;
  437. }
  438. ////////////////////////////////////////////////////////////////////////////////
  439. // CanReceiveWithoutBlocking
  440. ////////////////////////////////////////////////////////////////////////////////
  441. bool RSocket::CanReceiveWithoutBlocking(void)
  442. {
  443. bool bNoBlock = false;
  444. if (m_pProtocol != NULL)
  445. bNoBlock = m_pProtocol->CanReceiveWithoutBlocking();
  446. return bNoBlock;
  447. }
  448. ////////////////////////////////////////////////////////////////////////////////
  449. // Check socket's error status. If the socket is not open, then the return
  450. // value will be false (no error)
  451. ////////////////////////////////////////////////////////////////////////////////
  452. bool RSocket::IsError(void)
  453. {
  454. bool bResult = false;
  455. if (m_pProtocol != NULL)
  456. bResult = m_pProtocol->IsError();
  457. return bResult;
  458. }
  459. ////////////////////////////////////////////////////////////////////////////////
  460. // The specified protocol becomes the current protocol for all RSocket objects.
  461. // The protocol can NOT be changed while any sockets exist!!! In other words,
  462. // all RSocket objects must be destroyed before the protocol can be changed.
  463. //
  464. // Specifiying true for bAutoShutdown means that Shutdown() will be called
  465. // when the last RSocket object is destroyed. This is generally acceptable,
  466. // but could potentially cause problems if Startup() and Shutdown() are lengthy
  467. // processes, which is entirely protocol-dependant.
  468. //
  469. ////////////////////////////////////////////////////////////////////////////////
  470. // static
  471. short RSocket::Startup( // Returns 0 if successfull, non-zero otherwise
  472. RSocket::ProtoType prototype, // In: Protocol type
  473. bool bAutoShutdown) // In: Whether to perform auto Shutdown()
  474. {
  475. short sResult = 0;
  476. // Only do this once
  477. if (!ms_bDidStartup)
  478. {
  479. // Make sure no sockets exist
  480. if (ms_sNumSockets == 0)
  481. {
  482. // Set new stuff
  483. ms_prototype = prototype;
  484. ms_bAutoShutdown = bAutoShutdown;
  485. // Call the protocol's startup
  486. switch (ms_prototype)
  487. {
  488. case RSocket::TCPIP:
  489. ASSERT(sizeof(RProtocolBSDIP::AddressIP) == sizeof(RSocket::Address));
  490. sResult = RProtocolBSDIP::Startup();
  491. break;
  492. default:
  493. sResult = -1;
  494. TRACE("RSocket::Startup(): Unknown procol!\n");
  495. break;
  496. }
  497. }
  498. else
  499. {
  500. sResult = -1;
  501. TRACE("RSocket::Startup(): Can't change protocol -- %hd RSockets still exist!\n", (short)ms_sNumSockets);
  502. }
  503. if (sResult == 0)
  504. ms_bDidStartup = true;
  505. }
  506. return sResult;
  507. }
  508. ////////////////////////////////////////////////////////////////////////////////
  509. // Shutdown
  510. ////////////////////////////////////////////////////////////////////////////////
  511. // static
  512. void RSocket::Shutdown(void)
  513. {
  514. switch (ms_prototype)
  515. {
  516. case RSocket::TCPIP:
  517. RProtocolBSDIP::Shutdown();
  518. break;
  519. default:
  520. TRACE("RSocket::Shutdown(): Unknown protocol!\n");
  521. break;
  522. }
  523. ms_bDidStartup = false;
  524. // Clear protocol so we know it's safe to change it
  525. ms_prototype = RSocket::NO_PROTOCOL;
  526. }
  527. ////////////////////////////////////////////////////////////////////////////////
  528. // Get maximum datagram size. A value of 0 indicates that there is no
  529. // limitation on size.
  530. //
  531. // NOTE: This uses the protocol selected via RSocket::Startup(). If this
  532. // function is called before any protocol has been selected, it fails.
  533. ////////////////////////////////////////////////////////////////////////////////
  534. // static
  535. short RSocket::GetMaxDatagramSize( // Returns 0 on success, non-zero otherwise
  536. long* plSize) // Out: Maximum datagram size (in bytes)
  537. {
  538. short sResult = FAILURE;
  539. switch (ms_prototype)
  540. {
  541. case RSocket::TCPIP:
  542. sResult = RProtocolBSDIP::GetMaxDatagramSize(plSize);
  543. break;
  544. default:
  545. sResult = -1;
  546. TRACE("RSocket::GetMaxDatagramSize(): Unknown protocol!\n");
  547. break;
  548. }
  549. return sResult;
  550. }
  551. ////////////////////////////////////////////////////////////////////////////////
  552. // Get maximum number of sockets. This may be a system "global" value, which
  553. // means that if other applications are using sockets, then the number available
  554. // to this application may be lower than the returned value.
  555. //
  556. // NOTE: This uses the protocol selected via RSocket::Startup(). If this
  557. // function is called before any protocol has been selected, it fails.
  558. ////////////////////////////////////////////////////////////////////////////////
  559. // static
  560. short RSocket::GetMaxSockets( // Returns 0 on success, non-zero otherwise
  561. long* plNum) // Out: Maximum number of sockets
  562. {
  563. short sResult = FAILURE;
  564. switch (ms_prototype)
  565. {
  566. case RSocket::TCPIP:
  567. sResult = RProtocolBSDIP::GetMaxSockets(plNum);
  568. break;
  569. default:
  570. sResult = -1;
  571. TRACE("RSocket::GetMaxSockets(): Unknown protocol!\n");
  572. break;
  573. }
  574. return sResult;
  575. }
  576. ////////////////////////////////////////////////////////////////////////////////
  577. // Get address of specified host
  578. //
  579. // NOTE: This uses the protocol selected via RSocket::Startup(). If this
  580. // function is called before any protocol has been selected, it fails.
  581. ////////////////////////////////////////////////////////////////////////////////
  582. // static
  583. short RSocket::GetAddress( // Returns 0 on success, non-zero otherwise
  584. char* pszName, // In: Host's name or dotted addres (x.x.x.x)
  585. USHORT usPort, // In: Host's port number
  586. RSocket::Address* paddress) // Out: Address
  587. {
  588. short sResult = 0;
  589. // Get rid of leading and trailing whitespace
  590. char azName[RSP_MAX_PATH];
  591. if (strlen(pszName) < RSP_MAX_PATH)
  592. {
  593. // Skip over leading whitespace
  594. while ((*pszName != 0) && isspace(*pszName))
  595. pszName++;
  596. // Copy resulting string
  597. strcpy(azName, pszName);
  598. // Convert trailing whitespace to 0's
  599. long index;
  600. for (index = strlen(azName) - 1; index >= 0; index--)
  601. {
  602. if (isspace(azName[index]))
  603. azName[index] = 0;
  604. else
  605. break;
  606. }
  607. if (index < 0)
  608. {
  609. sResult = -1;
  610. TRACE("RSocket::GetAddress(): String is empty (after removing leading & trailing space)\n");
  611. }
  612. }
  613. else
  614. {
  615. sResult = -1;
  616. TRACE("RSocket::GetAddress(): Specified string is too long!\n");
  617. }
  618. // Make sure we don't accidently use this pointer -- must use azName instead!
  619. pszName = 0;
  620. // If the name is ready, try to get the address
  621. if (sResult == 0)
  622. {
  623. switch (ms_prototype)
  624. {
  625. case RSocket::TCPIP:
  626. sResult = RProtocolBSDIP::GetAddress(azName, usPort, paddress);
  627. break;
  628. default:
  629. sResult = -1;
  630. TRACE("RSocket::GetAddress(): Unknown protocol!\n");
  631. break;
  632. }
  633. }
  634. return sResult;
  635. }
  636. ////////////////////////////////////////////////////////////////////////////////
  637. // Create broadcast address using specified port
  638. ////////////////////////////////////////////////////////////////////////////////
  639. // static
  640. void RSocket::CreateBroadcastAddress(
  641. unsigned short usPort, // In: Port to broadcast to
  642. RSocket::Address* paddress) // Out: Broadcast address returned here
  643. {
  644. switch (ms_prototype)
  645. {
  646. case RSocket::TCPIP:
  647. RProtocolBSDIP::CreateBroadcastAddress(usPort, paddress);
  648. break;
  649. default:
  650. TRACE("RSocket::GetAddress(): Unknown protocol!\n");
  651. break;
  652. }
  653. }
  654. ////////////////////////////////////////////////////////////////////////////////
  655. // Get the port of an existing (valid) address
  656. //
  657. // NOTE: This uses the protocol selected via RSocket::Startup(). If this
  658. // function is called before any protocol has been selected, it fails.
  659. ////////////////////////////////////////////////////////////////////////////////
  660. // static
  661. unsigned short RSocket::GetAddressPort( // Returns the port number
  662. RSocket::Address* paddress) // In: Address to get port from
  663. {
  664. unsigned short usPort = 0;
  665. switch (ms_prototype)
  666. {
  667. case RSocket::TCPIP:
  668. usPort = RProtocolBSDIP::GetAddressPort(paddress);
  669. break;
  670. default:
  671. TRACE("RSocket::GetAddressPort(): Unknown protocol!\n");
  672. break;
  673. }
  674. return usPort;
  675. }
  676. ////////////////////////////////////////////////////////////////////////////////
  677. // Set the port of an existing (valid) address
  678. //
  679. // NOTE: This uses the protocol selected via RSocket::Startup(). If this
  680. // function is called before any protocol has been selected, it fails.
  681. ////////////////////////////////////////////////////////////////////////////////
  682. // static
  683. void RSocket::SetAddressPort(
  684. USHORT usPort, // In: New port number
  685. RSocket::Address* paddress) // I/O: Address whose port is to be set
  686. {
  687. switch (ms_prototype)
  688. {
  689. case RSocket::TCPIP:
  690. RProtocolBSDIP::SetAddressPort(usPort, paddress);
  691. break;
  692. default:
  693. TRACE("RSocket::SetAddressPort(): Unknown protocol!\n");
  694. break;
  695. }
  696. }
  697. ////////////////////////////////////////////////////////////////////////////////
  698. // Create specified protocol object
  699. ////////////////////////////////////////////////////////////////////////////////
  700. // since there can only be one modem in use (unless the user is stupid and wears
  701. // false antlers), we only need one instance on RProtocolTAPI, which is global:
  702. RSocket::RProtocol* RSocket::ConstructProtocol( // Returns pointer to prototype if successfull, 0 otherwise
  703. RSocket::ProtoType prototype) // In: Protocol type to create
  704. {
  705. RProtocol* pprotocol = 0;
  706. switch (prototype)
  707. {
  708. case RSocket::TCPIP:
  709. pprotocol = new RProtocolBSDIP;
  710. break;
  711. default:
  712. TRACE("RSocket::ConstructProtocol(): Unknown protocol!\n");
  713. break;
  714. }
  715. return pprotocol;
  716. }
  717. ////////////////////////////////////////////////////////////////////////////////
  718. // EOF
  719. ////////////////////////////////////////////////////////////////////////////////