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::
589 get_num_interfaces() {
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 }
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
static TrueClock * get_global_ptr()
Returns a pointer to the one TrueClock object in the world.
Definition: trueClock.I:68
Base functionality for a TCP connected socket This class is pretty useless by itself but it does hide...
Definition: socket_tcp.h:12
bool is_any() const
True if the address is zero.
std::string get_ip_string() const
Returns the IP address to which this address refers, formatted as a string.
Definition: netAddress.cxx:106
Base functionality for a INET domain Socket This call should be the starting point for all other unix...
Definition: socket_ip.h:27
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_polling() const
Returns true if the reader is a polling reader, i.e.
int SetBlocking()
Set the socket to block on subsequent calls to socket functions that address this socket.
Definition: socket_ip.h:191
get_interface
Returns the nth usable network interface detected on this machine.
This class can be used to convert text between multiple representations, e.g.
Definition: textEncoder.h:33
void scan_interfaces()
Repopulates the list reported by get_num_interface()/get_interface().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
Socket_Address GetPeerName(void) const
Wrapper on berkly getpeername...
Definition: socket_ip.h:253
static void force_yield()
Suspends the current thread for the rest of the current epoch.
Definition: thread.I:201
This is an abstract base class for a family of classes that listen for activity on a socket and respo...
Base functionality for a TCP rendezvous socket.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Base functionality for a combination UDP Reader and Writer.
Definition: socket_udp.h:24
Socket_IP * get_socket() const
Returns the internal Socket_IP that defines the connection.
Definition: connection.cxx:93
bool OpenForInput(unsigned short port)
Starts a UDP socket listening on a port.
bool SetToBroadCast()
Ask the OS to let us receive broadcast packets on this port.
Definition: socket_udp.h:63
Similar to MutexHolder, but for a light mutex.
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
PT(Connection) ConnectionManager
Opens a socket for sending and/or receiving UDP packets.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class handles threaded delivery of datagrams to various TCP or UDP sockets.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An interface to whatever real-time clock we might have available in the current environment.
Definition: trueClock.h:33
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_text
Returns the current text, as encoded via the current encoding system.
Definition: textEncoder.h:124
A simple place to store and manipulate tcp and port address for communication layer.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static int GetLastError()
Gets the last errcode from a socket operation.
Definition: socket_ip.h:140
void Close()
Closes a socket if it is open (allocated).
Definition: socket_ip.h:128
void clear()
Marks the content as empty.
Definition: socket_fdset.h:124
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...
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...
const Socket_Address & get_addr() const
Returns the Socket_Address for this address.
Definition: netAddress.cxx:138
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Represents a single TCP or UDP socket for input or output.
Definition: connection.h:29
bool flush()
Sends the most recently queued TCP datagram(s) now.
Definition: connection.cxx:173
bool OpenForListen(unsigned short port, int backlog_size=1024)
This function will initialize a listening Socket.
void set_wtext(const std::wstring &wtext)
Changes the text that is stored in the encoder.
Definition: textEncoder.I:443
Represents a network address to which UDP packets may be sent or to which a TCP socket may be bound.
Definition: netAddress.h:25
bool InitNoAddress()
Set this socket to work without a bound external address.