connectionManager.cxx 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. // Filename: connectionManager.cxx
  2. // Created by: jns (07Feb00)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "connectionManager.h"
  15. #include "connection.h"
  16. #include "connectionReader.h"
  17. #include "connectionWriter.h"
  18. #include "netAddress.h"
  19. #include "config_net.h"
  20. #include "lightMutexHolder.h"
  21. #include "trueClock.h"
  22. #if defined(WIN32_VC) || defined(WIN64_VC)
  23. #include <winsock2.h> // For gethostname()
  24. #else
  25. #include <net/if.h>
  26. #include <ifaddrs.h>
  27. #endif
  28. ////////////////////////////////////////////////////////////////////
  29. // Function: ConnectionManager::Constructor
  30. // Access: Published
  31. // Description:
  32. ////////////////////////////////////////////////////////////////////
  33. ConnectionManager::
  34. ConnectionManager() : _set_mutex("ConnectionManager::_set_mutex")
  35. {
  36. _interfaces_scanned = false;
  37. }
  38. ////////////////////////////////////////////////////////////////////
  39. // Function: ConnectionManager::Destructor
  40. // Access: Published, Virtual
  41. // Description:
  42. ////////////////////////////////////////////////////////////////////
  43. ConnectionManager::
  44. ~ConnectionManager() {
  45. // Notify all of our associated readers and writers that we're gone.
  46. Readers::iterator ri;
  47. for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
  48. (*ri)->clear_manager();
  49. }
  50. Writers::iterator wi;
  51. for (wi = _writers.begin(); wi != _writers.end(); ++wi) {
  52. (*wi)->clear_manager();
  53. }
  54. }
  55. ////////////////////////////////////////////////////////////////////
  56. // Function: ConnectionManager::open_UDP_connection
  57. // Access: Published
  58. // Description: Opens a socket for sending and/or receiving UDP
  59. // packets. If the port number is greater than zero,
  60. // the UDP connection will be opened for listening on
  61. // the indicated port; otherwise, it will be useful only
  62. // for sending.
  63. //
  64. // Use a ConnectionReader and ConnectionWriter to handle
  65. // the actual communication.
  66. ////////////////////////////////////////////////////////////////////
  67. PT(Connection) ConnectionManager::
  68. open_UDP_connection(int port) {
  69. return open_UDP_connection("", port);
  70. }
  71. ////////////////////////////////////////////////////////////////////
  72. // Function: ConnectionManager::open_UDP_connection
  73. // Access: Published
  74. // Description: Opens a socket for sending and/or receiving UDP
  75. // packets. If the port number is greater than zero,
  76. // the UDP connection will be opened for listening on
  77. // the indicated port; otherwise, it will be useful only
  78. // for sending.
  79. //
  80. // This variant accepts both a hostname and port to
  81. // listen on a particular interface; if the hostname is
  82. // empty, all interfaces will be available.
  83. //
  84. // If for_broadcast is true, this UDP connection will be
  85. // configured to send and/or receive messages on the
  86. // broadcast address (255.255.255.255); otherwise, these
  87. // messages may be automatically filtered by the OS.
  88. //
  89. // Use a ConnectionReader and ConnectionWriter to handle
  90. // the actual communication.
  91. ////////////////////////////////////////////////////////////////////
  92. PT(Connection) ConnectionManager::
  93. open_UDP_connection(const string &hostname, int port, bool for_broadcast) {
  94. Socket_UDP *socket = new Socket_UDP;
  95. if (port > 0) {
  96. NetAddress address;
  97. if (hostname.empty()) {
  98. address.set_any(port);
  99. } else {
  100. address.set_host(hostname, port);
  101. }
  102. if (!socket->OpenForInput(address.get_addr())) {
  103. if (hostname.empty()) {
  104. net_cat.error()
  105. << "Unable to bind to port " << port << " for UDP.\n";
  106. } else {
  107. net_cat.error()
  108. << "Unable to bind to " << hostname << ":" << port << " for UDP.\n";
  109. }
  110. delete socket;
  111. return PT(Connection)();
  112. }
  113. const char *broadcast_note = "";
  114. if (for_broadcast) {
  115. socket->SetToBroadCast();
  116. broadcast_note = "broadcast ";
  117. }
  118. if (hostname.empty()) {
  119. net_cat.info()
  120. << "Creating UDP " << broadcast_note << "connection for port " << port << "\n";
  121. } else {
  122. net_cat.info()
  123. << "Creating UDP " << broadcast_note << "connection for " << hostname << ":" << port << "\n";
  124. }
  125. } else {
  126. if (!socket->InitNoAddress()) {
  127. net_cat.error()
  128. << "Unable to initialize outgoing UDP.\n";
  129. delete socket;
  130. return PT(Connection)();
  131. }
  132. const char *broadcast_note = "";
  133. if (for_broadcast) {
  134. socket->SetToBroadCast();
  135. broadcast_note = "broadcast ";
  136. }
  137. net_cat.info()
  138. << "Creating outgoing UDP " << broadcast_note << "connection\n";
  139. }
  140. PT(Connection) connection = new Connection(this, socket);
  141. new_connection(connection);
  142. return connection;
  143. }
  144. ////////////////////////////////////////////////////////////////////
  145. // Function: ConnectionManager::open_TCP_server_rendezvous
  146. // Access: Published
  147. // Description: Creates a socket to be used as a rendezvous socket
  148. // for a server to listen for TCP connections. The
  149. // socket returned by this call should only be added to
  150. // a ConnectionListener (not to a generic
  151. // ConnectionReader).
  152. //
  153. // This variant of this method accepts a single port,
  154. // and will listen to that port on all available
  155. // interfaces.
  156. //
  157. // backlog is the maximum length of the queue of pending
  158. // connections.
  159. ////////////////////////////////////////////////////////////////////
  160. PT(Connection) ConnectionManager::
  161. open_TCP_server_rendezvous(int port, int backlog) {
  162. NetAddress address;
  163. address.set_any(port);
  164. return open_TCP_server_rendezvous(address, backlog);
  165. }
  166. ////////////////////////////////////////////////////////////////////
  167. // Function: ConnectionManager::open_TCP_server_rendezvous
  168. // Access: Published
  169. // Description: Creates a socket to be used as a rendezvous socket
  170. // for a server to listen for TCP connections. The
  171. // socket returned by this call should only be added to
  172. // a ConnectionListener (not to a generic
  173. // ConnectionReader).
  174. //
  175. // This variant of this method accepts a "hostname",
  176. // which is usually just an IP address in dotted
  177. // notation, and a port number. It will listen on the
  178. // interface indicated by the IP address. If the IP
  179. // address is empty string, it will listen on all
  180. // interfaces.
  181. //
  182. // backlog is the maximum length of the queue of pending
  183. // connections.
  184. ////////////////////////////////////////////////////////////////////
  185. PT(Connection) ConnectionManager::
  186. open_TCP_server_rendezvous(const string &hostname, int port, int backlog) {
  187. NetAddress address;
  188. if (hostname.empty()) {
  189. address.set_any(port);
  190. } else {
  191. address.set_host(hostname, port);
  192. }
  193. return open_TCP_server_rendezvous(address, backlog);
  194. }
  195. ////////////////////////////////////////////////////////////////////
  196. // Function: ConnectionManager::open_TCP_server_rendezvous
  197. // Access: Published
  198. // Description: Creates a socket to be used as a rendezvous socket
  199. // for a server to listen for TCP connections. The
  200. // socket returned by this call should only be added to
  201. // a ConnectionListener (not to a generic
  202. // ConnectionReader).
  203. //
  204. // This variant of this method accepts a NetAddress,
  205. // which allows you to specify a specific interface to
  206. // listen to.
  207. //
  208. // backlog is the maximum length of the queue of pending
  209. // connections.
  210. ////////////////////////////////////////////////////////////////////
  211. PT(Connection) ConnectionManager::
  212. open_TCP_server_rendezvous(const NetAddress &address, int backlog) {
  213. ostringstream strm;
  214. if (address.get_ip() == 0) {
  215. strm << "port " << address.get_port();
  216. } else {
  217. strm << address.get_ip_string() << ":" << address.get_port();
  218. }
  219. Socket_TCP_Listen *socket = new Socket_TCP_Listen;
  220. bool okflag = socket->OpenForListen(address.get_addr(), backlog);
  221. if (!okflag) {
  222. net_cat.info()
  223. << "Unable to listen to " << strm.str() << " for TCP.\n";
  224. delete socket;
  225. return PT(Connection)();
  226. }
  227. net_cat.info()
  228. << "Listening for TCP connections on " << strm.str() << "\n";
  229. PT(Connection) connection = new Connection(this, socket);
  230. new_connection(connection);
  231. return connection;
  232. }
  233. ////////////////////////////////////////////////////////////////////
  234. // Function: ConnectionManager::open_TCP_client_connection
  235. // Access: Published
  236. // Description: Attempts to establish a TCP client connection to a
  237. // server at the indicated address. If the connection
  238. // is not established within timeout_ms milliseconds, a
  239. // null connection is returned.
  240. ////////////////////////////////////////////////////////////////////
  241. PT(Connection) ConnectionManager::
  242. open_TCP_client_connection(const NetAddress &address, int timeout_ms) {
  243. Socket_TCP *socket = new Socket_TCP;
  244. // We always open the connection with non-blocking mode first, so we
  245. // can implement the timeout.
  246. bool okflag = socket->ActiveOpenNonBlocking(address.get_addr());
  247. if (okflag && socket->GetLastError() == LOCAL_CONNECT_BLOCKING) {
  248. // Now wait for the socket to connect.
  249. TrueClock *clock = TrueClock::get_global_ptr();
  250. double start = clock->get_short_time();
  251. Thread::force_yield();
  252. Socket_fdset fset;
  253. fset.setForSocket(*socket);
  254. int ready = fset.WaitForWrite(true, 0);
  255. while (ready == 0) {
  256. double elapsed = clock->get_short_time() - start;
  257. if (elapsed * 1000.0 > timeout_ms) {
  258. // Timeout.
  259. okflag = false;
  260. break;
  261. }
  262. Thread::force_yield();
  263. fset.setForSocket(*socket);
  264. ready = fset.WaitForWrite(true, 0);
  265. }
  266. }
  267. if (okflag) {
  268. // So, the connect() operation finished, but did it succeed or fail?
  269. if (socket->GetPeerName().GetIPAddressRaw() == 0) {
  270. // No peer means it failed.
  271. okflag = false;
  272. }
  273. }
  274. if (!okflag) {
  275. net_cat.error()
  276. << "Unable to open TCP connection to server "
  277. << address.get_ip_string() << " on port " << address.get_port() << "\n";
  278. delete socket;
  279. return PT(Connection)();
  280. }
  281. #if !defined(HAVE_THREADS) || !defined(SIMPLE_THREADS)
  282. // Now we have opened the socket in nonblocking mode. Unless we're
  283. // using SIMPLE_THREADS, though, we really want the socket in
  284. // blocking mode (since that's what we support here). Change it.
  285. socket->SetBlocking();
  286. #endif // SIMPLE_THREADS
  287. net_cat.info()
  288. << "Opened TCP connection to server " << address.get_ip_string()
  289. << " on port " << address.get_port() << "\n";
  290. PT(Connection) connection = new Connection(this, socket);
  291. new_connection(connection);
  292. return connection;
  293. }
  294. ////////////////////////////////////////////////////////////////////
  295. // Function: ConnectionManager::open_TCP_client_connection
  296. // Access: Published
  297. // Description: This is a shorthand version of the function to
  298. // directly establish communications to a named host and
  299. // port.
  300. ////////////////////////////////////////////////////////////////////
  301. PT(Connection) ConnectionManager::
  302. open_TCP_client_connection(const string &hostname, int port,
  303. int timeout_ms) {
  304. NetAddress address;
  305. if (!address.set_host(hostname, port)) {
  306. return PT(Connection)();
  307. }
  308. return open_TCP_client_connection(address, timeout_ms);
  309. }
  310. ////////////////////////////////////////////////////////////////////
  311. // Function: ConnectionManager::close_connection
  312. // Access: Published
  313. // Description: Terminates a UDP or TCP socket previously opened.
  314. // This also removes it from any associated
  315. // ConnectionReader or ConnectionListeners.
  316. //
  317. // The socket itself may not be immediately closed--it
  318. // will not be closed until all outstanding pointers to
  319. // it are cleared, including any pointers remaining in
  320. // NetDatagrams recently received from the socket.
  321. //
  322. // The return value is true if the connection was marked
  323. // to be closed, or false if close_connection() had
  324. // already been called (or the connection did not belong
  325. // to this ConnectionManager). In neither case can you
  326. // infer anything about whether the connection has
  327. // *actually* been closed yet based on the return value.
  328. ////////////////////////////////////////////////////////////////////
  329. bool ConnectionManager::
  330. close_connection(const PT(Connection) &connection) {
  331. if (connection != (Connection *)NULL) {
  332. connection->flush();
  333. }
  334. {
  335. LightMutexHolder holder(_set_mutex);
  336. Connections::iterator ci = _connections.find(connection);
  337. if (ci == _connections.end()) {
  338. // Already closed, or not part of this ConnectionManager.
  339. return false;
  340. }
  341. _connections.erase(ci);
  342. Readers::iterator ri;
  343. for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
  344. (*ri)->remove_connection(connection);
  345. }
  346. }
  347. Socket_IP *socket = connection->get_socket();
  348. // We can't *actually* close the connection right now, because
  349. // there might be outstanding pointers to it. But we can at least
  350. // shut it down. It will be eventually closed when all the
  351. // pointers let go.
  352. net_cat.info()
  353. << "Shutting down connection " << (void *)connection
  354. << " locally.\n";
  355. socket->Close();
  356. return true;
  357. }
  358. ////////////////////////////////////////////////////////////////////
  359. // Function: ConnectionManager::wait_for_readers
  360. // Access: Published
  361. // Description: Blocks the process for timeout number of seconds, or
  362. // until any data is available on any of the
  363. // non-threaded ConnectionReaders or
  364. // ConnectionListeners, whichever comes first. The
  365. // return value is true if there is data available (but
  366. // you have to iterate through all readers to find it),
  367. // or false if the timeout occurred without any data.
  368. //
  369. // If the timeout value is negative, this will block
  370. // forever or until data is available.
  371. //
  372. // This only works if all ConnectionReaders and
  373. // ConnectionListeners are non-threaded. If any
  374. // threaded ConnectionReaders are part of the
  375. // ConnectionManager, the timeout value is implicitly
  376. // treated as 0.
  377. ////////////////////////////////////////////////////////////////////
  378. bool ConnectionManager::
  379. wait_for_readers(double timeout) {
  380. bool block_forever = false;
  381. if (timeout < 0.0) {
  382. block_forever = true;
  383. timeout = 0.0;
  384. }
  385. TrueClock *clock = TrueClock::get_global_ptr();
  386. double now = clock->get_short_time();
  387. double stop = now + timeout;
  388. do {
  389. Socket_fdset fdset;
  390. fdset.clear();
  391. bool any_threaded = false;
  392. {
  393. LightMutexHolder holder(_set_mutex);
  394. Readers::iterator ri;
  395. for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
  396. ConnectionReader *reader = (*ri);
  397. if (reader->is_polling()) {
  398. // If it's a polling reader, we can wait for its socket.
  399. // (If it's a threaded reader, we can't do anything here.)
  400. reader->accumulate_fdset(fdset);
  401. } else {
  402. any_threaded = true;
  403. stop = now;
  404. block_forever = false;
  405. }
  406. }
  407. }
  408. double wait_timeout = get_net_max_block();
  409. if (!block_forever) {
  410. wait_timeout = min(wait_timeout, stop - now);
  411. }
  412. PN_uint32 wait_timeout_ms = (PN_uint32)(wait_timeout * 1000.0);
  413. if (any_threaded) {
  414. // If there are any threaded ConnectionReaders, we can't block
  415. // at all.
  416. wait_timeout_ms = 0;
  417. }
  418. #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
  419. // In the presence of SIMPLE_THREADS, we never wait at all,
  420. // but rather we yield the thread if we come up empty (so that
  421. // we won't block the entire process).
  422. wait_timeout_ms = 0;
  423. #endif
  424. int num_results = fdset.WaitForRead(false, wait_timeout_ms);
  425. if (num_results != 0) {
  426. // If we got an answer (or an error), return success. The
  427. // caller can then figure out what happened.
  428. if (num_results < 0) {
  429. // Go ahead and yield the timeslice if we got an error.
  430. Thread::force_yield();
  431. }
  432. return true;
  433. }
  434. // No answer yet, so yield and wait some more. We don't actually
  435. // block forever, even in the threaded case, so we can detect
  436. // ConnectionReaders being added and removed and such.
  437. Thread::force_yield();
  438. now = clock->get_short_time();
  439. } while (now < stop || block_forever);
  440. // Timeout occurred; no data.
  441. return false;
  442. }
  443. ////////////////////////////////////////////////////////////////////
  444. // Function: ConnectionManager::get_host_name
  445. // Access: Published, Static
  446. // Description: Returns the name of this particular machine on the
  447. // network, if available, or the empty string if the
  448. // hostname cannot be determined.
  449. ////////////////////////////////////////////////////////////////////
  450. string ConnectionManager::
  451. get_host_name() {
  452. char temp_buff[1024];
  453. if (gethostname(temp_buff, 1024) == 0) {
  454. return string(temp_buff);
  455. }
  456. return string();
  457. }
  458. ////////////////////////////////////////////////////////////////////
  459. // Function: ConnectionManager::scan_interfaces
  460. // Access: Published
  461. // Description: Repopulates the list reported by
  462. // get_num_interface()/get_interface(). It is not
  463. // necessary to call this explicitly, unless you want to
  464. // re-determine the connected interfaces (for instance,
  465. // if you suspect the hardware has recently changed).
  466. ////////////////////////////////////////////////////////////////////
  467. void ConnectionManager::
  468. scan_interfaces() {
  469. LightMutexHolder holder(_set_mutex);
  470. _interfaces.clear();
  471. _interfaces_scanned = true;
  472. #ifdef WIN32_VC
  473. // TODO.
  474. #else // WIN32_VC
  475. struct ifaddrs *ifa;
  476. if (getifaddrs(&ifa) != 0) {
  477. // Failure.
  478. net_cat.error()
  479. << "Failed to call getifaddrs\n";
  480. return;
  481. }
  482. struct ifaddrs *p = ifa;
  483. while (p != NULL) {
  484. if (p->ifa_addr->sa_family == AF_INET) {
  485. Interface interface;
  486. interface.set_name(p->ifa_name);
  487. if (p->ifa_addr != NULL) {
  488. interface.set_ip(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_addr)));
  489. }
  490. if (p->ifa_netmask != NULL) {
  491. interface.set_netmask(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_netmask)));
  492. }
  493. if ((p->ifa_flags & IFF_BROADCAST) && p->ifa_broadaddr != NULL) {
  494. interface.set_broadcast(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_broadaddr)));
  495. } else if ((p->ifa_flags & IFF_POINTOPOINT) && p->ifa_dstaddr != NULL) {
  496. interface.set_p2p(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_dstaddr)));
  497. }
  498. _interfaces.push_back(interface);
  499. }
  500. p = p->ifa_next;
  501. }
  502. freeifaddrs(ifa);
  503. #endif // WIN32_VC
  504. }
  505. ////////////////////////////////////////////////////////////////////
  506. // Function: ConnectionManager::get_num_interfaces
  507. // Access: Published
  508. // Description: This returns the number of usable network interfaces
  509. // detected on this machine. (Currently, only IPv4
  510. // interfaces are reported.) See scan_interfaces() to
  511. // repopulate this list.
  512. ////////////////////////////////////////////////////////////////////
  513. int ConnectionManager::
  514. get_num_interfaces() {
  515. if (!_interfaces_scanned) {
  516. scan_interfaces();
  517. }
  518. LightMutexHolder holder(_set_mutex);
  519. return _interfaces.size();
  520. }
  521. ////////////////////////////////////////////////////////////////////
  522. // Function: ConnectionManager::get_interface
  523. // Access: Published
  524. // Description: Returns the nth usable network interface detected on
  525. // this machine. (Currently, only IPv4 interfaces are
  526. // reported.) See scan_interfaces() to repopulate this
  527. // list.
  528. ////////////////////////////////////////////////////////////////////
  529. const ConnectionManager::Interface &ConnectionManager::
  530. get_interface(int n) {
  531. if (!_interfaces_scanned) {
  532. scan_interfaces();
  533. }
  534. LightMutexHolder holder(_set_mutex);
  535. nassertr(n >= 0 && n < (int)_interfaces.size(), _interfaces[0]);
  536. return _interfaces[n];
  537. }
  538. ////////////////////////////////////////////////////////////////////
  539. // Function: ConnectionManager::new_connection
  540. // Access: Protected
  541. // Description: This internal function is called whenever a new
  542. // connection is established. It allows the
  543. // ConnectionManager to save all of the pointers to open
  544. // connections so they can't be inadvertently deleted
  545. // until close_connection() is called.
  546. ////////////////////////////////////////////////////////////////////
  547. void ConnectionManager::
  548. new_connection(const PT(Connection) &connection) {
  549. LightMutexHolder holder(_set_mutex);
  550. _connections.insert(connection);
  551. }
  552. ////////////////////////////////////////////////////////////////////
  553. // Function: ConnectionManager::flush_read_connection
  554. // Access: Protected, Virtual
  555. // Description: An internal function called by ConnectionWriter only
  556. // when a write failure has occurred. This method
  557. // ensures that all of the read data has been flushed
  558. // from the pipe before the connection is fully removed.
  559. ////////////////////////////////////////////////////////////////////
  560. void ConnectionManager::
  561. flush_read_connection(Connection *connection) {
  562. Readers readers;
  563. {
  564. LightMutexHolder holder(_set_mutex);
  565. Connections::iterator ci = _connections.find(connection);
  566. if (ci == _connections.end()) {
  567. // Already closed, or not part of this ConnectionManager.
  568. return;
  569. }
  570. _connections.erase(ci);
  571. // Get a copy first, so we can release the lock before traversing.
  572. readers = _readers;
  573. }
  574. Readers::iterator ri;
  575. for (ri = readers.begin(); ri != readers.end(); ++ri) {
  576. (*ri)->flush_read_connection(connection);
  577. }
  578. Socket_IP *socket = connection->get_socket();
  579. socket->Close();
  580. }
  581. ////////////////////////////////////////////////////////////////////
  582. // Function: ConnectionManager::connection_reset
  583. // Access: Protected, Virtual
  584. // Description: An internal function called by the ConnectionReader,
  585. // ConnectionWriter, or ConnectionListener when a
  586. // connection has been externally reset. This adds the
  587. // connection to the queue of those which have recently
  588. // been reset.
  589. ////////////////////////////////////////////////////////////////////
  590. void ConnectionManager::
  591. connection_reset(const PT(Connection) &connection, bool okflag) {
  592. if (net_cat.is_info()) {
  593. if (okflag) {
  594. net_cat.info()
  595. << "Connection " << (void *)connection
  596. << " was closed normally by the other end";
  597. } else {
  598. net_cat.info()
  599. << "Lost connection " << (void *)connection
  600. << " unexpectedly\n";
  601. }
  602. }
  603. // Turns out we do need to explicitly mark the connection as closed
  604. // immediately, rather than waiting for the user to do it, since
  605. // otherwise we'll keep trying to listen for noise on the socket and
  606. // we'll always hear a "yes" answer.
  607. close_connection(connection);
  608. }
  609. ////////////////////////////////////////////////////////////////////
  610. // Function: ConnectionManager::add_reader
  611. // Access: Protected
  612. // Description: This internal function is called by ConnectionReader
  613. // when it is constructed.
  614. ////////////////////////////////////////////////////////////////////
  615. void ConnectionManager::
  616. add_reader(ConnectionReader *reader) {
  617. LightMutexHolder holder(_set_mutex);
  618. _readers.insert(reader);
  619. }
  620. ////////////////////////////////////////////////////////////////////
  621. // Function: ConnectionManager::remove_reader
  622. // Access: Protected
  623. // Description: This internal function is called by ConnectionReader
  624. // when it is destructed.
  625. ////////////////////////////////////////////////////////////////////
  626. void ConnectionManager::
  627. remove_reader(ConnectionReader *reader) {
  628. LightMutexHolder holder(_set_mutex);
  629. _readers.erase(reader);
  630. }
  631. ////////////////////////////////////////////////////////////////////
  632. // Function: ConnectionManager::add_writer
  633. // Access: Protected
  634. // Description: This internal function is called by ConnectionWriter
  635. // when it is constructed.
  636. ////////////////////////////////////////////////////////////////////
  637. void ConnectionManager::
  638. add_writer(ConnectionWriter *writer) {
  639. LightMutexHolder holder(_set_mutex);
  640. _writers.insert(writer);
  641. }
  642. ////////////////////////////////////////////////////////////////////
  643. // Function: ConnectionManager::remove_writer
  644. // Access: Protected
  645. // Description: This internal function is called by ConnectionWriter
  646. // when it is destructed.
  647. ////////////////////////////////////////////////////////////////////
  648. void ConnectionManager::
  649. remove_writer(ConnectionWriter *writer) {
  650. LightMutexHolder holder(_set_mutex);
  651. _writers.erase(writer);
  652. }
  653. ////////////////////////////////////////////////////////////////////
  654. // Function: ConnectionManager::Interface::Output
  655. // Access: Published
  656. // Description:
  657. ////////////////////////////////////////////////////////////////////
  658. void ConnectionManager::Interface::
  659. output(ostream &out) const {
  660. out << get_name() << " [";
  661. if (has_ip()) {
  662. out << " " << get_ip();
  663. }
  664. if (has_netmask()) {
  665. out << " netmask " << get_netmask();
  666. }
  667. if (has_broadcast()) {
  668. out << " broadcast " << get_broadcast();
  669. }
  670. if (has_p2p()) {
  671. out << " p2p " << get_p2p();
  672. }
  673. out << " ]";
  674. }