Panda3D
Loading...
Searching...
No Matches
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
36using std::stringstream;
37using std::string;
38
39/**
40 *
41 */
42ConnectionManager::
43ConnectionManager() : _set_mutex("ConnectionManager::_set_mutex")
44{
45 _interfaces_scanned = false;
46}
47
48/**
49 *
50 */
51ConnectionManager::
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 */
74PT(Connection) ConnectionManager::
75open_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 */
96PT(Connection) ConnectionManager::
97open_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 */
170PT(Connection) ConnectionManager::
171open_TCP_server_rendezvous(uint16_t port, int backlog) {
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 */
200PT(Connection) ConnectionManager::
201open_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 */
221PT(Connection) ConnectionManager::
222open_TCP_server_rendezvous(const NetAddress &address, int backlog) {
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 */
244PT(Connection) ConnectionManager::
245open_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 */
307PT(Connection) ConnectionManager::
308open_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 */
333close_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 */
383wait_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 */
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;
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 */
590 if (!_interfaces_scanned) {
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 */
602get_interface(size_t n) {
603 if (!_interfaces_scanned) {
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 */
617void ConnectionManager::
618new_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 */
628void ConnectionManager::
629flush_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 */
657void ConnectionManager::
658connection_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 */
683void ConnectionManager::
684add_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 */
692void ConnectionManager::
693remove_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 */
702void ConnectionManager::
703add_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 */
711void ConnectionManager::
712remove_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 */
720string ConnectionManager::
721format_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 */
736void ConnectionManager::Interface::
737output(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}
get_num_interfaces
This returns the number of usable network interfaces detected on this machine.
get_host_name
Returns the name of this particular machine on the network, if available, or the empty string if the ...
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...
void scan_interfaces()
Repopulates the list reported by get_num_interface()/get_interface().
get_interface
Returns the nth usable network interface detected on this machine.
PT(Connection) open_TCP_client_connection(const std bool close_connection(const PT(Connection) &connection)
Terminates a UDP or TCP socket previously opened.
This is an abstract base class for a family of classes that listen for activity on a socket and respo...
bool is_polling() const
Returns true if the reader is a polling reader, i.e.
This class handles threaded delivery of datagrams to various TCP or UDP sockets.
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.
Socket_IP * get_socket() const
Returns the internal Socket_IP that defines the connection.
Similar to MutexHolder, but for a light mutex.
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 set_host(const std::string &hostname, int port)
Sets the address up to refer to a particular port on a particular host.
std::string get_ip_string() const
Returns the IP address to which this address refers, formatted as a string.
const Socket_Address & get_addr() const
Returns the Socket_Address for this address.
uint32_t get_ip() const
Returns the IP address to which this address refers, as a 32-bit integer, in host byte order.
A simple place to store and manipulate tcp and port address for communication layer.
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...
bool is_any() const
True if the address is zero.
Base functionality for a INET domain Socket This call should be the starting point for all other unix...
Definition socket_ip.h:27
static int GetLastError()
Gets the last errcode from a socket operation.
Definition socket_ip.h:140
int SetBlocking()
Set the socket to block on subsequent calls to socket functions that address this socket.
Definition socket_ip.h:191
void Close()
Closes a socket if it is open (allocated).
Definition socket_ip.h:128
Socket_Address GetPeerName(void) const
Wrapper on berkly getpeername...
Definition socket_ip.h:253
Base functionality for a TCP rendezvous socket.
bool OpenForListen(unsigned short port, int backlog_size=1024)
This function will initialize a listening Socket.
Base functionality for a TCP connected socket This class is pretty useless by itself but it does hide...
Definition socket_tcp.h:12
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
bool InitNoAddress()
Set this socket to work without a bound external address.
bool OpenForInput(unsigned short port)
Starts a UDP socket listening on a port.
Base functionality for a combination UDP Reader and Writer.
Definition socket_udp.h:24
bool SetToBroadCast()
Ask the OS to let us receive broadcast packets on this port.
Definition socket_udp.h:63
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.
void clear()
Marks the content as empty.
This class can be used to convert text between multiple representations, e.g.
Definition textEncoder.h:33
get_text
Returns the current text, as encoded via the current encoding system.
void set_wtext(const std::wstring &wtext)
Changes the text that is stored in the encoder.
static void force_yield()
Suspends the current thread for the rest of the current epoch.
Definition thread.I:201
An interface to whatever real-time clock we might have available in the current environment.
Definition trueClock.h:33
static TrueClock * get_global_ptr()
Returns a pointer to the one TrueClock object in the world.
Definition trueClock.I:68
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.