Panda3D
connectionManager.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file connectionManager.cxx
10  * @author jns
11  * @date 2000-02-07
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 "socket_udp.h"
21 #include "socket_tcp_listen.h"
22 #include "lightMutexHolder.h"
23 #include "trueClock.h"
24 
25 #if defined(CPPPARSER)
26 #elif defined(WIN32_VC) || defined(WIN64_VC)
27 #include <winsock2.h> // For gethostname()
28 #include <Iphlpapi.h> // For GetAdaptersAddresses()
29 #elif defined(__ANDROID__)
30 #include <net/if.h>
31 #else
32 #include <net/if.h>
33 #include <ifaddrs.h>
34 #endif
35 
36 using std::stringstream;
37 using std::string;
38 
39 /**
40  *
41  */
42 ConnectionManager::
43 ConnectionManager() : _set_mutex("ConnectionManager::_set_mutex")
44 {
45  _interfaces_scanned = false;
46 }
47 
48 /**
49  *
50  */
51 ConnectionManager::
52 ~ConnectionManager() {
53  // Notify all of our associated readers and writers that we're gone.
54  Readers::iterator ri;
55  for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
56  (*ri)->clear_manager();
57  }
58  Writers::iterator wi;
59  for (wi = _writers.begin(); wi != _writers.end(); ++wi) {
60  (*wi)->clear_manager();
61  }
62 }
63 
64 
65 /**
66  * Opens a socket for sending and/or receiving UDP packets. If the port
67  * number is greater than zero, the UDP connection will be opened for
68  * listening on the indicated port; otherwise, it will be useful only for
69  * sending.
70  *
71  * Use a ConnectionReader and ConnectionWriter to handle the actual
72  * communication.
73  */
74 PT(Connection) ConnectionManager::
75 open_UDP_connection(uint16_t port) {
76  return open_UDP_connection("", port);
77 }
78 
79 /**
80  * Opens a socket for sending and/or receiving UDP packets. If the port
81  * number is greater than zero, the UDP connection will be opened for
82  * listening on the indicated port; otherwise, it will be useful only for
83  * sending.
84  *
85  * This variant accepts both a hostname and port to listen on a particular
86  * interface; if the hostname is empty, all interfaces will be available,
87  * both IPv4 and IPv6.
88  *
89  * If for_broadcast is true, this UDP connection will be configured to send
90  * and/or receive messages on the broadcast address (255.255.255.255);
91  * otherwise, these messages may be automatically filtered by the OS.
92  *
93  * Use a ConnectionReader and ConnectionWriter to handle the actual
94  * communication.
95  */
96 PT(Connection) ConnectionManager::
97 open_UDP_connection(const string &hostname, uint16_t port, bool for_broadcast) {
98  Socket_UDP *socket = new Socket_UDP;
99 
100  if (port > 0) {
101  bool okflag;
102  NetAddress address;
103  if (hostname.empty()) {
104  // The empty string means to listen on both IPv4 and IPv6 interfaces.
105  okflag = socket->OpenForInput(port);
106  } else {
107  address.set_host(hostname, port);
108  okflag = socket->OpenForInput(address.get_addr());
109  }
110 
111  if (!okflag) {
112  if (hostname.empty()) {
113  net_cat.error()
114  << "Unable to bind to port " << port << " for UDP.\n";
115  } else {
116  net_cat.error()
117  << "Unable to bind to " << address << " for UDP.\n";
118  }
119  delete socket;
120  return PT(Connection)();
121  }
122 
123  const char *broadcast_note = "";
124  if (for_broadcast) {
125  socket->SetToBroadCast();
126  broadcast_note = "broadcast ";
127  }
128 
129  if (hostname.empty()) {
130  net_cat.info()
131  << "Creating UDP " << broadcast_note << "connection for port " << port << "\n";
132  } else {
133  net_cat.info()
134  << "Creating UDP " << broadcast_note << "connection for " << address << "\n";
135  }
136 
137  } else {
138  if (!socket->InitNoAddress()) {
139  net_cat.error()
140  << "Unable to initialize outgoing UDP.\n";
141  delete socket;
142  return PT(Connection)();
143  }
144 
145  const char *broadcast_note = "";
146  if (for_broadcast) {
147  socket->SetToBroadCast();
148  broadcast_note = "broadcast ";
149  }
150 
151  net_cat.info()
152  << "Creating outgoing UDP " << broadcast_note << "connection\n";
153  }
154 
155  PT(Connection) connection = new Connection(this, socket);
156  new_connection(connection);
157  return connection;
158 }
159 
160 /**
161  * Creates a socket to be used as a rendezvous socket for a server to listen
162  * for TCP connections. The socket returned by this call should only be added
163  * to a ConnectionListener (not to a generic ConnectionReader).
164  *
165  * This variant of this method accepts a single port, and will listen to that
166  * port on all available interfaces, both IPv4 and IPv6.
167  *
168  * backlog is the maximum length of the queue of pending connections.
169  */
170 PT(Connection) ConnectionManager::
171 open_TCP_server_rendezvous(uint16_t port, int backlog) {
172  Socket_TCP_Listen *socket = new Socket_TCP_Listen;
173  if (!socket->OpenForListen(port, backlog)) {
174  net_cat.info()
175  << "Unable to listen to port " << port << " for TCP.\n";
176  delete socket;
177  return PT(Connection)();
178  }
179 
180  net_cat.info()
181  << "Listening for TCP connections on port " << port << "\n";
182 
183  PT(Connection) connection = new Connection(this, socket);
184  new_connection(connection);
185  return connection;
186 }
187 
188 /**
189  * Creates a socket to be used as a rendezvous socket for a server to listen
190  * for TCP connections. The socket returned by this call should only be added
191  * to a ConnectionListener (not to a generic ConnectionReader).
192  *
193  * This variant of this method accepts a "hostname", which is usually just an
194  * IP address in dotted notation, and a port number. It will listen on the
195  * interface indicated by the IP address. If the IP address is empty string,
196  * it will listen on all interfaces.
197  *
198  * backlog is the maximum length of the queue of pending connections.
199  */
200 PT(Connection) ConnectionManager::
201 open_TCP_server_rendezvous(const string &hostname, uint16_t port, int backlog) {
202  if (hostname.empty()) {
203  return open_TCP_server_rendezvous(port, backlog);
204  } else {
205  NetAddress address;
206  address.set_host(hostname, port);
207  return open_TCP_server_rendezvous(address, backlog);
208  }
209 }
210 
211 /**
212  * Creates a socket to be used as a rendezvous socket for a server to listen
213  * for TCP connections. The socket returned by this call should only be added
214  * to a ConnectionListener (not to a generic ConnectionReader).
215  *
216  * This variant of this method accepts a NetAddress, which allows you to
217  * specify a specific interface to listen to.
218  *
219  * backlog is the maximum length of the queue of pending connections.
220  */
221 PT(Connection) ConnectionManager::
222 open_TCP_server_rendezvous(const NetAddress &address, int backlog) {
223  Socket_TCP_Listen *socket = new Socket_TCP_Listen;
224  if (!socket->OpenForListen(address.get_addr(), backlog)) {
225  net_cat.info()
226  << "Unable to listen to " << address << " for TCP.\n";
227  delete socket;
228  return PT(Connection)();
229  }
230 
231  net_cat.info()
232  << "Listening for TCP connections on " << address << "\n";
233 
234  PT(Connection) connection = new Connection(this, socket);
235  new_connection(connection);
236  return connection;
237 }
238 
239 /**
240  * Attempts to establish a TCP client connection to a server at the indicated
241  * address. If the connection is not established within timeout_ms
242  * milliseconds, a null connection is returned.
243  */
244 PT(Connection) ConnectionManager::
245 open_TCP_client_connection(const NetAddress &address, int timeout_ms) {
246  Socket_TCP *socket = new Socket_TCP;
247 
248  // We always open the connection with non-blocking mode first, so we can
249  // implement the timeout.
250  bool okflag = socket->ActiveOpenNonBlocking(address.get_addr());
251  if (okflag && socket->GetLastError() == LOCAL_CONNECT_BLOCKING) {
252  // Now wait for the socket to connect.
254  double start = clock->get_short_time();
256  Socket_fdset fset;
257  fset.setForSocket(*socket);
258  int ready = fset.WaitForWrite(true, 0);
259  while (ready == 0) {
260  double elapsed = clock->get_short_time() - start;
261  if (elapsed * 1000.0 > timeout_ms) {
262  // Timeout.
263  okflag = false;
264  break;
265  }
267  fset.setForSocket(*socket);
268  ready = fset.WaitForWrite(true, 0);
269  }
270  }
271 
272  if (okflag) {
273  // So, the connect() operation finished, but did it succeed or fail?
274  if (socket->GetPeerName().is_any()) {
275  // No peer means it failed.
276  okflag = false;
277  }
278  }
279 
280  if (!okflag) {
281  net_cat.error()
282  << "Unable to open TCP connection to server " << address << "\n";
283  delete socket;
284  return PT(Connection)();
285  }
286 
287 #if !defined(HAVE_THREADS) || !defined(SIMPLE_THREADS)
288  // Now we have opened the socket in nonblocking mode. Unless we're using
289  // SIMPLE_THREADS, though, we really want the socket in blocking mode (since
290  // that's what we support here). Change it.
291  socket->SetBlocking();
292 
293 #endif // SIMPLE_THREADS
294 
295  net_cat.info()
296  << "Opened TCP connection to server " << address << "\n";
297 
298  PT(Connection) connection = new Connection(this, socket);
299  new_connection(connection);
300  return connection;
301 }
302 
303 /**
304  * This is a shorthand version of the function to directly establish
305  * communications to a named host and port.
306  */
307 PT(Connection) ConnectionManager::
308 open_TCP_client_connection(const string &hostname, uint16_t port,
309  int timeout_ms) {
310  NetAddress address;
311  if (!address.set_host(hostname, port)) {
312  return PT(Connection)();
313  }
314 
315  return open_TCP_client_connection(address, timeout_ms);
316 }
317 
318 /**
319  * Terminates a UDP or TCP socket previously opened. This also removes it
320  * from any associated ConnectionReader or ConnectionListeners.
321  *
322  * The socket itself may not be immediately closed--it will not be closed
323  * until all outstanding pointers to it are cleared, including any pointers
324  * remaining in NetDatagrams recently received from the socket.
325  *
326  * The return value is true if the connection was marked to be closed, or
327  * false if close_connection() had already been called (or the connection did
328  * not belong to this ConnectionManager). In neither case can you infer
329  * anything about whether the connection has *actually* been closed yet based
330  * on the return value.
331  */
332 bool ConnectionManager::
333 close_connection(const PT(Connection) &connection) {
334  if (connection != nullptr) {
335  connection->flush();
336  }
337 
338  {
339  LightMutexHolder holder(_set_mutex);
340  Connections::iterator ci = _connections.find(connection);
341  if (ci == _connections.end()) {
342  // Already closed, or not part of this ConnectionManager.
343  return false;
344  }
345  _connections.erase(ci);
346 
347  Readers::iterator ri;
348  for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
349  (*ri)->remove_connection(connection);
350  }
351  }
352 
353  Socket_IP *socket = connection->get_socket();
354 
355  // We can't *actually* close the connection right now, because there might
356  // be outstanding pointers to it. But we can at least shut it down. It
357  // will be eventually closed when all the pointers let go.
358 
359  net_cat.info()
360  << "Shutting down connection " << (void *)connection
361  << " locally.\n";
362  socket->Close();
363 
364  return true;
365 }
366 
367 
368 /**
369  * Blocks the process for timeout number of seconds, or until any data is
370  * available on any of the non-threaded ConnectionReaders or
371  * ConnectionListeners, whichever comes first. The return value is true if
372  * there is data available (but you have to iterate through all readers to
373  * find it), or false if the timeout occurred without any data.
374  *
375  * If the timeout value is negative, this will block forever or until data is
376  * available.
377  *
378  * This only works if all ConnectionReaders and ConnectionListeners are non-
379  * threaded. If any threaded ConnectionReaders are part of the
380  * ConnectionManager, the timeout value is implicitly treated as 0.
381  */
383 wait_for_readers(double timeout) {
384  bool block_forever = false;
385  if (timeout < 0.0) {
386  block_forever = true;
387  timeout = 0.0;
388  }
389 
391  double now = clock->get_short_time();
392  double stop = now + timeout;
393  do {
394  Socket_fdset fdset;
395  fdset.clear();
396  bool any_threaded = false;
397 
398  {
399  LightMutexHolder holder(_set_mutex);
400 
401  Readers::iterator ri;
402  for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
403  ConnectionReader *reader = (*ri);
404  if (reader->is_polling()) {
405  // If it's a polling reader, we can wait for its socket. (If it's a
406  // threaded reader, we can't do anything here.)
407  reader->accumulate_fdset(fdset);
408  } else {
409  any_threaded = true;
410  stop = now;
411  block_forever = false;
412  }
413  }
414  }
415 
416  double wait_timeout = get_net_max_block();
417  if (!block_forever) {
418  wait_timeout = std::min(wait_timeout, stop - now);
419  }
420 
421  uint32_t wait_timeout_ms = (uint32_t)(wait_timeout * 1000.0);
422  if (any_threaded) {
423  // If there are any threaded ConnectionReaders, we can't block at all.
424  wait_timeout_ms = 0;
425  }
426 #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
427  // In the presence of SIMPLE_THREADS, we never wait at all, but rather we
428  // yield the thread if we come up empty (so that we won't block the entire
429  // process).
430  wait_timeout_ms = 0;
431 #endif
432  int num_results = fdset.WaitForRead(false, wait_timeout_ms);
433  if (num_results != 0) {
434  // If we got an answer (or an error), return success. The caller can
435  // then figure out what happened.
436  if (num_results < 0) {
437  // Go ahead and yield the timeslice if we got an error.
439  }
440  return true;
441  }
442 
443  // No answer yet, so yield and wait some more. We don't actually block
444  // forever, even in the threaded case, so we can detect ConnectionReaders
445  // being added and removed and such.
447 
448  now = clock->get_short_time();
449  } while (now < stop || block_forever);
450 
451  // Timeout occurred; no data.
452  return false;
453 }
454 
455 /**
456  * Returns the name of this particular machine on the network, if available,
457  * or the empty string if the hostname cannot be determined.
458  */
459 string ConnectionManager::
460 get_host_name() {
461  char temp_buff[1024];
462  if (gethostname(temp_buff, 1024) == 0) {
463  return string(temp_buff);
464  }
465 
466  return string();
467 }
468 
469 /**
470  * Repopulates the list reported by get_num_interface()/get_interface(). It
471  * is not necessary to call this explicitly, unless you want to re-determine
472  * the connected interfaces (for instance, if you suspect the hardware has
473  * recently changed).
474  */
477  LightMutexHolder holder(_set_mutex);
478  _interfaces.clear();
479  _interfaces_scanned = true;
480 
481 #ifdef WIN32_VC
482  int flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
483  ULONG family = support_ipv6 ? AF_UNSPEC : AF_INET;
484  ULONG buffer_size = 0;
485  ULONG result = GetAdaptersAddresses(family, flags, nullptr, nullptr, &buffer_size);
486  if (result == ERROR_BUFFER_OVERFLOW) {
487  IP_ADAPTER_ADDRESSES *addresses = (IP_ADAPTER_ADDRESSES *)PANDA_MALLOC_ARRAY(buffer_size);
488  result = GetAdaptersAddresses(family, flags, nullptr, addresses, &buffer_size);
489  if (result == ERROR_SUCCESS) {
490  IP_ADAPTER_ADDRESSES *p = addresses;
491  while (p != nullptr) {
492  // p->AdapterName appears to be a GUID. Not sure if this is actually
493  // useful to anyone; we'll store the "friendly name" instead.
494  TextEncoder encoder;
495  encoder.set_wtext(std::wstring(p->FriendlyName));
496  string friendly_name = encoder.get_text();
497 
498  Interface iface;
499  iface.set_name(friendly_name);
500 
501  if (p->PhysicalAddressLength > 0) {
502  iface.set_mac_address(format_mac_address((const unsigned char *)p->PhysicalAddress, p->PhysicalAddressLength));
503  }
504 
505  if (p->OperStatus == IfOperStatusUp) {
506  // Prefixes are a linked list, in the order Network IP, Adapter IP,
507  // Broadcast IP (plus more).
508  NetAddress addresses[3];
509  IP_ADAPTER_PREFIX *m = p->FirstPrefix;
510  int mc = 0;
511  while (m != nullptr && mc < 3) {
512  addresses[mc] = NetAddress(Socket_Address(*m->Address.lpSockaddr));
513  m = m->Next;
514  ++mc;
515  }
516 
517  if (mc > 1) {
518  iface.set_ip(addresses[1]);
519  }
520 
521  if (mc > 2) {
522  iface.set_broadcast(addresses[2]);
523 
524  // Now, we can infer the netmask by the difference between the
525  // network address (the first address) and the broadcast address
526  // (the last address).
527  if (addresses[0].get_addr().get_family() == AF_INET &&
528  addresses[2].get_addr().get_family() == AF_INET) {
529  uint32_t netmask = addresses[0].get_ip() - addresses[2].get_ip() - 1;
530  Socket_Address sa;
531  sa.set_host(netmask, 0);
532  iface.set_netmask(NetAddress(sa));
533  }
534  }
535  }
536 
537  _interfaces.push_back(iface);
538  p = p->Next;
539  }
540  }
541  PANDA_FREE_ARRAY(addresses);
542  }
543 
544 #elif defined(__ANDROID__)
545  // TODO: implementation using netlink_socket?
546 
547 #else // WIN32_VC
548  struct ifaddrs *ifa;
549  if (getifaddrs(&ifa) != 0) {
550  // Failure.
551  net_cat.error()
552  << "Failed to call getifaddrs\n";
553  return;
554  }
555 
556  struct ifaddrs *p = ifa;
557  while (p != nullptr) {
558  if (p->ifa_addr->sa_family == AF_INET ||
559  (support_ipv6 && p->ifa_addr->sa_family == AF_INET6)) {
560  Interface iface;
561  iface.set_name(p->ifa_name);
562  if (p->ifa_addr != nullptr) {
563  iface.set_ip(NetAddress(Socket_Address(*p->ifa_addr)));
564  }
565  if (p->ifa_netmask != nullptr) {
566  iface.set_netmask(NetAddress(Socket_Address(*p->ifa_netmask)));
567  }
568  if ((p->ifa_flags & IFF_BROADCAST) && p->ifa_broadaddr != nullptr) {
569  iface.set_broadcast(NetAddress(Socket_Address(*p->ifa_broadaddr)));
570  } else if ((p->ifa_flags & IFF_POINTOPOINT) && p->ifa_dstaddr != nullptr) {
571  iface.set_p2p(NetAddress(Socket_Address(*p->ifa_dstaddr)));
572  }
573  _interfaces.push_back(iface);
574  }
575 
576  p = p->ifa_next;
577  }
578 
579  freeifaddrs(ifa);
580 
581 #endif // WIN32_VC
582 }
583 
584 /**
585  * This returns the number of usable network interfaces detected on this
586  * machine. See scan_interfaces() to repopulate this list.
587  */
588 size_t ConnectionManager::
590  if (!_interfaces_scanned) {
591  scan_interfaces();
592  }
593  LightMutexHolder holder(_set_mutex);
594  return _interfaces.size();
595 }
596 
597 /**
598  * Returns the nth usable network interface detected on this machine.
599  * See scan_interfaces() to repopulate this list.
600  */
602 get_interface(size_t n) {
603  if (!_interfaces_scanned) {
604  scan_interfaces();
605  }
606  LightMutexHolder holder(_set_mutex);
607  nassertr(n < _interfaces.size(), _interfaces[0]);
608  return _interfaces[n];
609 }
610 
611 /**
612  * This internal function is called whenever a new connection is established.
613  * It allows the ConnectionManager to save all of the pointers to open
614  * connections so they can't be inadvertently deleted until close_connection()
615  * is called.
616  */
617 void ConnectionManager::
618 new_connection(const PT(Connection) &connection) {
619  LightMutexHolder holder(_set_mutex);
620  _connections.insert(connection);
621 }
622 
623 /**
624  * An internal function called by ConnectionWriter only when a write failure
625  * has occurred. This method ensures that all of the read data has been
626  * flushed from the pipe before the connection is fully removed.
627  */
628 void ConnectionManager::
629 flush_read_connection(Connection *connection) {
630  Readers readers;
631  {
632  LightMutexHolder holder(_set_mutex);
633  Connections::iterator ci = _connections.find(connection);
634  if (ci == _connections.end()) {
635  // Already closed, or not part of this ConnectionManager.
636  return;
637  }
638  _connections.erase(ci);
639 
640  // Get a copy first, so we can release the lock before traversing.
641  readers = _readers;
642  }
643  Readers::iterator ri;
644  for (ri = readers.begin(); ri != readers.end(); ++ri) {
645  (*ri)->flush_read_connection(connection);
646  }
647 
648  Socket_IP *socket = connection->get_socket();
649  socket->Close();
650 }
651 
652 /**
653  * An internal function called by the ConnectionReader, ConnectionWriter, or
654  * ConnectionListener when a connection has been externally reset. This adds
655  * the connection to the queue of those which have recently been reset.
656  */
657 void ConnectionManager::
658 connection_reset(const PT(Connection) &connection, bool okflag) {
659  if (net_cat.is_info()) {
660  if (okflag) {
661  net_cat.info()
662  << "Connection " << (void *)connection
663  << " was closed normally by the other end";
664 
665  } else {
666  net_cat.info()
667  << "Lost connection " << (void *)connection
668  << " unexpectedly\n";
669  }
670  }
671 
672  // Turns out we do need to explicitly mark the connection as closed
673  // immediately, rather than waiting for the user to do it, since otherwise
674  // we'll keep trying to listen for noise on the socket and we'll always hear
675  // a "yes" answer.
676  close_connection(connection);
677 }
678 
679 /**
680  * This internal function is called by ConnectionReader when it is
681  * constructed.
682  */
683 void ConnectionManager::
684 add_reader(ConnectionReader *reader) {
685  LightMutexHolder holder(_set_mutex);
686  _readers.insert(reader);
687 }
688 
689 /**
690  * This internal function is called by ConnectionReader when it is destructed.
691  */
692 void ConnectionManager::
693 remove_reader(ConnectionReader *reader) {
694  LightMutexHolder holder(_set_mutex);
695  _readers.erase(reader);
696 }
697 
698 /**
699  * This internal function is called by ConnectionWriter when it is
700  * constructed.
701  */
702 void ConnectionManager::
703 add_writer(ConnectionWriter *writer) {
704  LightMutexHolder holder(_set_mutex);
705  _writers.insert(writer);
706 }
707 
708 /**
709  * This internal function is called by ConnectionWriter when it is destructed.
710  */
711 void ConnectionManager::
712 remove_writer(ConnectionWriter *writer) {
713  LightMutexHolder holder(_set_mutex);
714  _writers.erase(writer);
715 }
716 
717 /**
718  * Formats a device's MAC address into a string.
719  */
720 string ConnectionManager::
721 format_mac_address(const unsigned char *data, size_t data_size) {
722  std::stringstream strm;
723  for (size_t di = 0; di < data_size; ++di) {
724  if (di != 0) {
725  strm << "-";
726  }
727  strm << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)data[di];
728  }
729 
730  return strm.str();
731 }
732 
733 /**
734  *
735  */
736 void ConnectionManager::Interface::
737 output(std::ostream &out) const {
738  out << get_name() << " [";
739  if (has_ip()) {
740  out << " " << get_ip().get_ip_string();
741  }
742  if (has_netmask()) {
743  out << " netmask " << get_netmask().get_ip_string();
744  }
745  if (has_broadcast()) {
746  out << " broadcast " << get_broadcast().get_ip_string();
747  }
748  if (has_p2p()) {
749  out << " p2p " << get_p2p().get_ip_string();
750  }
751  out << " ]";
752 }
Socket_IP
Base functionality for a INET domain Socket This call should be the starting point for all other unix...
Definition: socket_ip.h:27
LightMutexHolder
Similar to MutexHolder, but for a light mutex.
Definition: lightMutexHolder.h:25
ConnectionManager::get_num_interfaces
get_num_interfaces
This returns the number of usable network interfaces detected on this machine.
Definition: connectionManager.h:109
TextEncoder::set_wtext
void set_wtext(const std::wstring &wtext)
Changes the text that is stored in the encoder.
Definition: textEncoder.I:443
Socket_TCP
Base functionality for a TCP connected socket This class is pretty useless by itself but it does hide...
Definition: socket_tcp.h:12
ConnectionManager::Interface
Definition: connectionManager.h:64
trueClock.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Connection::get_socket
Socket_IP * get_socket() const
Returns the internal Socket_IP that defines the connection.
Definition: connection.cxx:93
Socket_IP::GetPeerName
Socket_Address GetPeerName(void) const
Wrapper on berkly getpeername...
Definition: socket_ip.h:253
Socket_Address::is_any
bool is_any() const
True if the address is zero.
Definition: socket_address.I:235
Socket_fdset::WaitForWrite
int WaitForWrite(bool zeroFds, uint32_t sleep_time=0xffffffff)
This is the function that will wait till one of the sockets is ready for writing.
Definition: socket_fdset.h:142
Socket_TCP_Listen
Base functionality for a TCP rendezvous socket.
Definition: socket_tcp_listen.h:11
connectionWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Connection
Represents a single TCP or UDP socket for input or output.
Definition: connection.h:29
Socket_UDP::SetToBroadCast
bool SetToBroadCast()
Ask the OS to let us receive broadcast packets on this port.
Definition: socket_udp.h:63
NetAddress::get_addr
const Socket_Address & get_addr() const
Returns the Socket_Address for this address.
Definition: netAddress.cxx:138
Socket_UDP_Incoming::OpenForInput
bool OpenForInput(unsigned short port)
Starts a UDP socket listening on a port.
Definition: socket_udp_incoming.h:75
ConnectionManager::get_interface
get_interface
Returns the nth usable network interface detected on this machine.
Definition: connectionManager.h:109
socket_udp.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Socket_TCP::ActiveOpenNonBlocking
bool ActiveOpenNonBlocking(const Socket_Address &theaddress)
This function will try and set the socket up for active open to a specified address and port provided...
Definition: socket_tcp.h:142
lightMutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ConnectionManager::scan_interfaces
void scan_interfaces()
Repopulates the list reported by get_num_interface()/get_interface().
Definition: connectionManager.cxx:476
Socket_TCP_Listen::OpenForListen
bool OpenForListen(unsigned short port, int backlog_size=1024)
This function will initialize a listening Socket.
Definition: socket_tcp_listen.h:45
ConnectionReader::is_polling
bool is_polling() const
Returns true if the reader is a polling reader, i.e.
Definition: connectionReader.I:18
Socket_fdset
Definition: socket_fdset.h:16
NetAddress
Represents a network address to which UDP packets may be sent or to which a TCP socket may be bound.
Definition: netAddress.h:25
Socket_UDP
Base functionality for a combination UDP Reader and Writer.
Definition: socket_udp.h:24
ConnectionWriter
This class handles threaded delivery of datagrams to various TCP or UDP sockets.
Definition: connectionWriter.h:35
config_net.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Socket_IP::Close
void Close()
Closes a socket if it is open (allocated).
Definition: socket_ip.h:128
Socket_Address::set_host
bool set_host(const std::string &hostname, unsigned short port)
This function will take a port and string-based TCP address and initialize the address with this info...
Definition: socket_address.cxx:23
netAddress.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Socket_UDP_Incoming::InitNoAddress
bool InitNoAddress()
Set this socket to work without a bound external address.
Definition: socket_udp_incoming.h:57
Connection::flush
bool flush()
Sends the most recently queued TCP datagram(s) now.
Definition: connection.cxx:173
connection.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Socket_fdset::clear
void clear()
Marks the content as empty.
Definition: socket_fdset.h:124
NetAddress::get_ip_string
std::string get_ip_string() const
Returns the IP address to which this address refers, formatted as a string.
Definition: netAddress.cxx:106
TrueClock::get_global_ptr
static TrueClock * get_global_ptr()
Returns a pointer to the one TrueClock object in the world.
Definition: trueClock.I:68
PT
PT(Connection) ConnectionManager
Opens a socket for sending and/or receiving UDP packets.
Definition: connectionManager.cxx:74
TrueClock
An interface to whatever real-time clock we might have available in the current environment.
Definition: trueClock.h:33
TextEncoder::get_text
get_text
Returns the current text, as encoded via the current encoding system.
Definition: textEncoder.h:124
Socket_Address
A simple place to store and manipulate tcp and port address for communication layer.
Definition: socket_address.h:25
Socket_IP::GetLastError
static int GetLastError()
Gets the last errcode from a socket operation.
Definition: socket_ip.h:140
NetAddress::get_ip
uint32_t get_ip() const
Returns the IP address to which this address refers, as a 32-bit integer, in host byte order.
Definition: netAddress.cxx:116
TextEncoder
This class can be used to convert text between multiple representations, e.g.
Definition: textEncoder.h:33
NetAddress::set_host
bool set_host(const std::string &hostname, int port)
Sets the address up to refer to a particular port on a particular host.
Definition: netAddress.cxx:66
connectionManager.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
connectionReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ConnectionManager::wait_for_readers
bool wait_for_readers(double timeout)
Blocks the process for timeout number of seconds, or until any data is available on any of the non-th...
Definition: connectionManager.cxx:383
ConnectionManager::get_host_name
get_host_name
Returns the name of this particular machine on the network, if available, or the empty string if the ...
Definition: connectionManager.h:111
Thread::force_yield
static void force_yield()
Suspends the current thread for the rest of the current epoch.
Definition: thread.I:201
Socket_IP::SetBlocking
int SetBlocking()
Set the socket to block on subsequent calls to socket functions that address this socket.
Definition: socket_ip.h:191
ConnectionReader
This is an abstract base class for a family of classes that listen for activity on a socket and respo...
Definition: connectionReader.h:50