21 #include "socket_tcp_listen.h" 25 #if defined(CPPPARSER) 26 #elif defined(WIN32_VC) || defined(WIN64_VC) 29 #elif defined(__ANDROID__) 36 using std::stringstream;
43 ConnectionManager() : _set_mutex(
"ConnectionManager::_set_mutex")
45 _interfaces_scanned =
false;
52 ~ConnectionManager() {
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();
75 open_UDP_connection(uint16_t port) {
76 return open_UDP_connection(
"", port);
97 open_UDP_connection(
const string &hostname, uint16_t port,
bool for_broadcast) {
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";
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";
145 const char *broadcast_note =
"";
148 broadcast_note =
"broadcast ";
152 <<
"Creating outgoing UDP " << broadcast_note <<
"connection\n";
156 new_connection(connection);
171 open_TCP_server_rendezvous(uint16_t port,
int backlog) {
175 <<
"Unable to listen to port " << port <<
" for TCP.\n";
181 <<
"Listening for TCP connections on port " << port <<
"\n";
184 new_connection(connection);
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);
207 return open_TCP_server_rendezvous(address, backlog);
222 open_TCP_server_rendezvous(
const NetAddress &address,
int backlog) {
226 <<
"Unable to listen to " << address <<
" for TCP.\n";
232 <<
"Listening for TCP connections on " << address <<
"\n";
235 new_connection(connection);
245 open_TCP_client_connection(
const NetAddress &address,
int timeout_ms) {
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";
287 #if !defined(HAVE_THREADS) || !defined(SIMPLE_THREADS) 293 #endif // SIMPLE_THREADS 296 <<
"Opened TCP connection to server " << address <<
"\n";
299 new_connection(connection);
308 open_TCP_client_connection(
const string &hostname, uint16_t port,
311 if (!address.
set_host(hostname, port)) {
315 return open_TCP_client_connection(address, timeout_ms);
332 bool ConnectionManager::
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) {
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);
459 string ConnectionManager::
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);
588 size_t ConnectionManager::
589 get_num_interfaces() {
590 if (!_interfaces_scanned) {
594 return _interfaces.size();
603 if (!_interfaces_scanned) {
607 nassertr(n < _interfaces.size(), _interfaces[0]);
608 return _interfaces[n];
617 void ConnectionManager::
620 _connections.insert(connection);
628 void ConnectionManager::
629 flush_read_connection(
Connection *connection) {
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);
657 void ConnectionManager::
658 connection_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";
676 close_connection(connection);
683 void ConnectionManager::
686 _readers.insert(reader);
692 void ConnectionManager::
695 _readers.erase(reader);
702 void ConnectionManager::
705 _writers.insert(writer);
711 void ConnectionManager::
714 _writers.erase(writer);
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) {
727 strm << std::hex << std::setw(2) << std::setfill(
'0') << (
unsigned int)data[di];
736 void ConnectionManager::Interface::
737 output(std::ostream &out)
const {
738 out << get_name() <<
" [";
745 if (has_broadcast()) {
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.
static TrueClock * get_global_ptr()
Returns a pointer to the one TrueClock object in the world.
Base functionality for a TCP connected socket This class is pretty useless by itself but it does hide...
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.
Base functionality for a INET domain Socket This call should be the starting point for all other unix...
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.
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.
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...
Socket_Address GetPeerName(void) const
Wrapper on berkly getpeername...
static void force_yield()
Suspends the current thread for the rest of the current epoch.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Base functionality for a combination UDP Reader and Writer.
Socket_IP * get_socket() const
Returns the internal Socket_IP that defines the connection.
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.
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.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_text
Returns the current text, as encoded via the current encoding system.
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.
void Close()
Closes a socket if it is open (allocated).
void clear()
Marks the content as empty.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Represents a single TCP or UDP socket for input or output.
bool flush()
Sends the most recently queued TCP datagram(s) now.
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.
Represents a network address to which UDP packets may be sent or to which a TCP socket may be bound.
bool InitNoAddress()
Set this socket to work without a bound external address.