21#include "socket_tcp_listen.h"
26#elif defined(WIN32_VC) || defined(WIN64_VC)
29#elif defined(__ANDROID__)
36using std::stringstream;
43ConnectionManager() : _set_mutex(
"ConnectionManager::_set_mutex")
45 _interfaces_scanned =
false;
55 for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
56 (*ri)->clear_manager();
59 for (wi = _writers.begin(); wi != _writers.end(); ++wi) {
60 (*wi)->clear_manager();
74PT(Connection) ConnectionManager::
75open_UDP_connection(uint16_t port) {
76 return open_UDP_connection(
"", port);
96PT(Connection) ConnectionManager::
97open_UDP_connection(
const string &hostname, uint16_t port,
bool for_broadcast) {
98 Socket_UDP *socket =
new Socket_UDP;
103 if (hostname.empty()) {
112 if (hostname.empty()) {
114 <<
"Unable to bind to port " << port <<
" for UDP.\n";
117 <<
"Unable to bind to " << address <<
" for UDP.\n";
120 return PT(Connection)();
123 const char *broadcast_note =
"";
126 broadcast_note =
"broadcast ";
129 if (hostname.empty()) {
131 <<
"Creating UDP " << broadcast_note <<
"connection for port " << port <<
"\n";
134 <<
"Creating UDP " << broadcast_note <<
"connection for " << address <<
"\n";
140 <<
"Unable to initialize outgoing UDP.\n";
142 return PT(Connection)();
145 const char *broadcast_note =
"";
148 broadcast_note =
"broadcast ";
152 <<
"Creating outgoing UDP " << broadcast_note <<
"connection\n";
155 PT(Connection) connection =
new Connection(
this, socket);
156 new_connection(connection);
170PT(Connection) ConnectionManager::
171open_TCP_server_rendezvous(uint16_t port,
int backlog) {
172 Socket_TCP_Listen *socket =
new Socket_TCP_Listen;
175 <<
"Unable to listen to port " << port <<
" for TCP.\n";
177 return PT(Connection)();
181 <<
"Listening for TCP connections on port " << port <<
"\n";
183 PT(Connection) connection =
new Connection(
this, socket);
184 new_connection(connection);
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);
207 return open_TCP_server_rendezvous(address, backlog);
221PT(Connection) ConnectionManager::
222open_TCP_server_rendezvous(
const NetAddress &address,
int backlog) {
223 Socket_TCP_Listen *socket =
new Socket_TCP_Listen;
226 <<
"Unable to listen to " << address <<
" for TCP.\n";
228 return PT(Connection)();
232 <<
"Listening for TCP connections on " << address <<
"\n";
234 PT(Connection) connection =
new Connection(
this, socket);
235 new_connection(connection);
244PT(Connection) ConnectionManager::
245open_TCP_client_connection(
const NetAddress &address,
int timeout_ms) {
246 Socket_TCP *socket =
new Socket_TCP;
251 if (okflag && socket->
GetLastError() == LOCAL_CONNECT_BLOCKING) {
254 double start = clock->get_short_time();
257 fset.setForSocket(*socket);
260 double elapsed = clock->get_short_time() - start;
261 if (elapsed * 1000.0 > timeout_ms) {
267 fset.setForSocket(*socket);
282 <<
"Unable to open TCP connection to server " << address <<
"\n";
284 return PT(Connection)();
287#if !defined(HAVE_THREADS) || !defined(SIMPLE_THREADS)
296 <<
"Opened TCP connection to server " << address <<
"\n";
298 PT(Connection) connection =
new Connection(
this, socket);
299 new_connection(connection);
307PT(Connection) ConnectionManager::
308open_TCP_client_connection(
const string &hostname, uint16_t port,
311 if (!address.
set_host(hostname, port)) {
312 return PT(Connection)();
315 return open_TCP_client_connection(address, timeout_ms);
334 if (connection !=
nullptr) {
340 Connections::iterator ci = _connections.find(connection);
341 if (ci == _connections.end()) {
345 _connections.erase(ci);
347 Readers::iterator ri;
348 for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
349 (*ri)->remove_connection(connection);
360 <<
"Shutting down connection " << (
void *)connection
384 bool block_forever =
false;
386 block_forever =
true;
391 double now = clock->get_short_time();
392 double stop = now + timeout;
396 bool any_threaded =
false;
401 Readers::iterator ri;
402 for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
403 ConnectionReader *reader = (*ri);
407 reader->accumulate_fdset(fdset);
411 block_forever =
false;
416 double wait_timeout = get_net_max_block();
417 if (!block_forever) {
418 wait_timeout = std::min(wait_timeout, stop - now);
421 uint32_t wait_timeout_ms = (uint32_t)(wait_timeout * 1000.0);
426#if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
432 int num_results = fdset.WaitForRead(
false, wait_timeout_ms);
433 if (num_results != 0) {
436 if (num_results < 0) {
448 now = clock->get_short_time();
449 }
while (now < stop || block_forever);
461 char temp_buff[1024];
462 if (gethostname(temp_buff, 1024) == 0) {
463 return string(temp_buff);
479 _interfaces_scanned =
true;
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) {
495 encoder.
set_wtext(std::wstring(p->FriendlyName));
496 string friendly_name = encoder.
get_text();
499 iface.set_name(friendly_name);
501 if (p->PhysicalAddressLength > 0) {
502 iface.set_mac_address(format_mac_address((
const unsigned char *)p->PhysicalAddress, p->PhysicalAddressLength));
505 if (p->OperStatus == IfOperStatusUp) {
509 IP_ADAPTER_PREFIX *m = p->FirstPrefix;
511 while (m !=
nullptr && mc < 3) {
518 iface.set_ip(addresses[1]);
522 iface.set_broadcast(addresses[2]);
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;
537 _interfaces.push_back(iface);
541 PANDA_FREE_ARRAY(addresses);
544#elif defined(__ANDROID__)
549 if (getifaddrs(&ifa) != 0) {
552 <<
"Failed to call getifaddrs\n";
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)) {
561 iface.set_name(p->ifa_name);
562 if (p->ifa_addr !=
nullptr) {
565 if (p->ifa_netmask !=
nullptr) {
568 if ((p->ifa_flags & IFF_BROADCAST) && p->ifa_broadaddr !=
nullptr) {
570 }
else if ((p->ifa_flags & IFF_POINTOPOINT) && p->ifa_dstaddr !=
nullptr) {
573 _interfaces.push_back(iface);
590 if (!_interfaces_scanned) {
593 LightMutexHolder holder(_set_mutex);
594 return _interfaces.size();
603 if (!_interfaces_scanned) {
606 LightMutexHolder holder(_set_mutex);
607 nassertr(n < _interfaces.size(), _interfaces[0]);
608 return _interfaces[n];
617void ConnectionManager::
618new_connection(
const PT(Connection) &connection) {
619 LightMutexHolder holder(_set_mutex);
620 _connections.insert(connection);
628void ConnectionManager::
629flush_read_connection(Connection *connection) {
632 LightMutexHolder holder(_set_mutex);
633 Connections::iterator ci = _connections.find(connection);
634 if (ci == _connections.end()) {
638 _connections.erase(ci);
643 Readers::iterator ri;
644 for (ri = readers.begin(); ri != readers.end(); ++ri) {
645 (*ri)->flush_read_connection(connection);
657void ConnectionManager::
658connection_reset(
const PT(Connection) &connection,
bool okflag) {
659 if (net_cat.is_info()) {
662 <<
"Connection " << (
void *)connection
663 <<
" was closed normally by the other end";
667 <<
"Lost connection " << (
void *)connection
668 <<
" unexpectedly\n";
683void ConnectionManager::
685 LightMutexHolder holder(_set_mutex);
686 _readers.insert(reader);
692void ConnectionManager::
694 LightMutexHolder holder(_set_mutex);
695 _readers.erase(reader);
702void ConnectionManager::
704 LightMutexHolder holder(_set_mutex);
705 _writers.insert(writer);
711void ConnectionManager::
713 LightMutexHolder holder(_set_mutex);
714 _writers.erase(writer);
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) {
727 strm << std::hex << std::setw(2) << std::setfill(
'0') << (
unsigned int)data[di];
736void ConnectionManager::Interface::
737output(std::ostream &out)
const {
738 out << get_name() <<
" [";
740 out <<
" " << get_ip().get_ip_string();
743 out <<
" netmask " << get_netmask().get_ip_string();
745 if (has_broadcast()) {
746 out <<
" broadcast " << get_broadcast().get_ip_string();
749 out <<
" p2p " << get_p2p().get_ip_string();
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.
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.
bool set_host(const std::string &hostname, int port)
Sets the address up to refer to a particular port on a particular host.
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...
static int GetLastError()
Gets the last errcode from a socket operation.
int SetBlocking()
Set the socket to block on subsequent calls to socket functions that address this socket.
void Close()
Closes a socket if it is open (allocated).
Socket_Address GetPeerName(void) const
Wrapper on berkly getpeername...
bool OpenForListen(unsigned short port, int backlog_size=1024)
This function will initialize a listening Socket.
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...
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.
bool SetToBroadCast()
Ask the OS to let us receive broadcast packets on this port.
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.
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.
An interface to whatever real-time clock we might have available in the current environment.
static TrueClock * get_global_ptr()
Returns a pointer to the one TrueClock object in the world.
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.