15 #include "connectionManager.h"
16 #include "connection.h"
17 #include "connectionReader.h"
18 #include "connectionWriter.h"
19 #include "netAddress.h"
20 #include "config_net.h"
21 #include "socket_udp.h"
22 #include "socket_tcp_listen.h"
23 #include "lightMutexHolder.h"
24 #include "trueClock.h"
26 #if defined(WIN32_VC) || defined(WIN64_VC)
29 #elif defined(ANDROID)
42 ConnectionManager() : _set_mutex(
"ConnectionManager::_set_mutex")
44 _interfaces_scanned =
false;
53 ~ConnectionManager() {
56 for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
57 (*ri)->clear_manager();
60 for (wi = _writers.begin(); wi != _writers.end(); ++wi) {
61 (*wi)->clear_manager();
79 open_UDP_connection(
int port) {
80 return open_UDP_connection(
"", port);
105 open_UDP_connection(const
string &hostname,
int port,
bool for_broadcast) {
110 if (hostname.empty()) {
117 if (hostname.empty()) {
119 <<
"Unable to bind to port " << port <<
" for UDP.\n";
122 <<
"Unable to bind to " << hostname <<
":" << port <<
" for UDP.\n";
128 const char *broadcast_note =
"";
131 broadcast_note =
"broadcast ";
134 if (hostname.empty()) {
136 <<
"Creating UDP " << broadcast_note <<
"connection for port " << port <<
"\n";
139 <<
"Creating UDP " << broadcast_note <<
"connection for " << hostname <<
":" << port <<
"\n";
145 <<
"Unable to initialize outgoing UDP.\n";
150 const char *broadcast_note =
"";
153 broadcast_note =
"broadcast ";
157 <<
"Creating outgoing UDP " << broadcast_note <<
"connection\n";
161 new_connection(connection);
184 open_TCP_server_rendezvous(
int port,
int backlog) {
187 return open_TCP_server_rendezvous(address, backlog);
210 open_TCP_server_rendezvous(const
string &hostname,
int port,
int backlog) {
212 if (hostname.empty()) {
217 return open_TCP_server_rendezvous(address, backlog);
237 open_TCP_server_rendezvous(const
NetAddress &address,
int backlog) {
239 if (address.get_ip() == 0) {
240 strm <<
"port " << address.get_port();
242 strm << address.get_ip_string() <<
":" << address.get_port();
246 bool okflag = socket->
OpenForListen(address.get_addr(), backlog);
249 <<
"Unable to listen to " << strm.str() <<
" for TCP.\n";
255 <<
"Listening for TCP connections on " << strm.str() <<
"\n";
258 new_connection(connection);
271 open_TCP_client_connection(const
NetAddress &address,
int timeout_ms) {
277 if (okflag && socket->
GetLastError() == LOCAL_CONNECT_BLOCKING) {
280 double start = clock->get_short_time();
283 fset.setForSocket(*socket);
286 double elapsed = clock->get_short_time() - start;
287 if (elapsed * 1000.0 > timeout_ms) {
293 fset.setForSocket(*socket);
308 <<
"Unable to open TCP connection to server "
309 << address.get_ip_string() <<
" on port " << address.get_port() <<
"\n";
314 #if !defined(HAVE_THREADS) || !defined(SIMPLE_THREADS)
320 #endif // SIMPLE_THREADS
323 <<
"Opened TCP connection to server " << address.get_ip_string()
324 <<
" on port " << address.get_port() <<
"\n";
327 new_connection(connection);
339 open_TCP_client_connection(const
string &hostname,
int port,
342 if (!address.
set_host(hostname, port)) {
346 return open_TCP_client_connection(address, timeout_ms);
376 Connections::iterator ci = _connections.find(connection);
377 if (ci == _connections.end()) {
381 _connections.erase(ci);
383 Readers::iterator ri;
384 for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
385 (*ri)->remove_connection(connection);
397 <<
"Shutting down connection " << (
void *)connection
427 bool block_forever =
false;
429 block_forever =
true;
434 double now = clock->get_short_time();
435 double stop = now + timeout;
439 bool any_threaded =
false;
444 Readers::iterator ri;
445 for (ri = _readers.begin(); ri != _readers.end(); ++ri) {
450 reader->accumulate_fdset(fdset);
454 block_forever =
false;
459 double wait_timeout = get_net_max_block();
460 if (!block_forever) {
461 wait_timeout = min(wait_timeout, stop - now);
464 PN_uint32 wait_timeout_ms = (PN_uint32)(wait_timeout * 1000.0);
470 #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
476 int num_results = fdset.WaitForRead(
false, wait_timeout_ms);
477 if (num_results != 0) {
480 if (num_results < 0) {
492 now = clock->get_short_time();
493 }
while (now < stop || block_forever);
508 char temp_buff[1024];
509 if (gethostname(temp_buff, 1024) == 0) {
510 return string(temp_buff);
529 _interfaces_scanned =
true;
532 int flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
533 ULONG buffer_size = 0;
534 ULONG result = GetAdaptersAddresses(AF_INET, flags, NULL, NULL, &buffer_size);
535 if (result == ERROR_BUFFER_OVERFLOW) {
536 IP_ADAPTER_ADDRESSES *addresses = (IP_ADAPTER_ADDRESSES *)PANDA_MALLOC_ARRAY(buffer_size);
537 result = GetAdaptersAddresses(AF_INET, flags, NULL, addresses, &buffer_size);
538 if (result == ERROR_SUCCESS) {
539 IP_ADAPTER_ADDRESSES *p = addresses;
545 encoder.
set_wtext(wstring(p->FriendlyName));
546 string friendly_name = encoder.
get_text();
549 iface.set_name(friendly_name);
551 if (p->PhysicalAddressLength > 0) {
552 iface.set_mac_address(format_mac_address((
const unsigned char *)p->PhysicalAddress, p->PhysicalAddressLength));
555 if (p->OperStatus == IfOperStatusUp) {
559 IP_ADAPTER_PREFIX *m = p->FirstPrefix;
561 while (m != NULL && mc < 3) {
568 iface.set_ip(addresses[1]);
572 iface.set_broadcast(addresses[2]);
577 PN_uint32 netmask = addresses[0].
get_ip() - addresses[2].
get_ip() - 1;
584 _interfaces.push_back(iface);
588 PANDA_FREE_ARRAY(addresses);
591 #elif defined(ANDROID)
596 if (getifaddrs(&ifa) != 0) {
599 <<
"Failed to call getifaddrs\n";
603 struct ifaddrs *p = ifa;
605 if (p->ifa_addr->sa_family == AF_INET) {
607 iface.set_name(p->ifa_name);
608 if (p->ifa_addr != NULL) {
611 if (p->ifa_netmask != NULL) {
614 if ((p->ifa_flags & IFF_BROADCAST) && p->ifa_broadaddr != NULL) {
616 }
else if ((p->ifa_flags & IFF_POINTOPOINT) && p->ifa_dstaddr != NULL) {
619 _interfaces.push_back(iface);
640 if (!_interfaces_scanned) {
644 return _interfaces.size();
657 if (!_interfaces_scanned) {
661 nassertr(n >= 0 && n < (
int)_interfaces.size(), _interfaces[0]);
662 return _interfaces[n];
674 void ConnectionManager::
675 new_connection(
const PT(
Connection) &connection) {
677 _connections.insert(connection);
688 void ConnectionManager::
689 flush_read_connection(
Connection *connection) {
693 Connections::iterator ci = _connections.find(connection);
694 if (ci == _connections.end()) {
698 _connections.erase(ci);
703 Readers::iterator ri;
704 for (ri = readers.begin(); ri != readers.end(); ++ri) {
705 (*ri)->flush_read_connection(connection);
721 void ConnectionManager::
722 connection_reset(
const PT(
Connection) &connection,
bool okflag) {
723 if (net_cat.is_info()) {
726 <<
"Connection " << (
void *)connection
727 <<
" was closed normally by the other end";
731 <<
"Lost connection " << (
void *)connection
732 <<
" unexpectedly\n";
749 void ConnectionManager::
752 _readers.insert(reader);
761 void ConnectionManager::
764 _readers.erase(reader);
773 void ConnectionManager::
776 _writers.insert(writer);
785 void ConnectionManager::
788 _writers.erase(writer);
796 string ConnectionManager::
797 format_mac_address(
const unsigned char *data,
int data_size) {
799 for (
int di = 0; di < data_size; ++di) {
803 strm << hex << setw(2) << setfill(
'0') << (
unsigned int)data[di];
814 void ConnectionManager::Interface::
815 output(ostream &out)
const {
816 out << get_name() <<
" [";
818 out <<
" " << get_ip();
821 out <<
" netmask " << get_netmask();
823 if (has_broadcast()) {
824 out <<
" broadcast " << get_broadcast();
827 out <<
" p2p " << get_p2p();
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...
int get_num_interfaces()
This returns the number of usable network interfaces detected on this machine.
bool set_any(int port)
Sets the address up to refer to a particular port, but not to any particular IP.
bool close_connection(const PT(Connection)&connection)
Terminates a UDP or TCP socket previously opened.
Base functionality for a INET domain Socket this call should be the starting point for all other unix...
int SetBlocking()
Set the socket to block on subsequent calls to socket functions that address this socket...
This class can be used to convert text between multiple representations, e.g.
bool InitNoAddress()
This will set a udp up for targeted sends.
void scan_interfaces()
Repopulates the list reported by get_num_interface()/get_interface().
const Socket_Address & get_addr() const
Returns the Socket_Address for this address.
The primary interface to the low-level networking layer in this package.
string get_text() const
Returns the current text, as encoded via the current encoding system.
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 OpenForListen(const Socket_Address &Inaddess, int backlog_size=1024)
This function will initialize a listening Socket.
static void force_yield()
Suspends the current thread for the rest of the current epoch.
Socket_Address GetPeerName(void) const
Wrapper on berkly getpeername...
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.
bool set_host(const string &hostname, int port)
Sets the address up to refer to a particular port on a particular host.
PN_uint32 get_ip() const
Returns the IP address to which this address refers, as a 32-bit integer, in host byte order...
Socket_IP * get_socket() const
Returns the internal Socket_IP that defines the connection.
Base functionality for a combination UDP Reader and Writer.
bool SetToBroadCast()
Ask the OS to let us receive BROADCASt packets on this port.
Similar to MutexHolder, but for a light mutex.
This class handles threaded delivery of datagrams to various TCP or UDP sockets.
static string get_host_name()
Returns the name of this particular machine on the network, if available, or the empty string if the ...
An interface to whatever real-time clock we might have available in the current environment.
A simple place to store and munipulate tcp and port address for communication layer.
unsigned long GetIPAddressRaw() const
Return a RAW sockaddr_in.
bool set_host(const std::string &hostname, int port)
This function will take a port and string-based TCP address and initialize the address with this info...
bool is_polling() const
Returns true if the reader is a polling reader, i.e.
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...
const Interface & get_interface(int n)
Returns the nth usable network interface detected on this machine.
bool OpenForInput(const Socket_Address &address)
Starts a UDP socket listening on a port.
void set_wtext(const wstring &wtext)
Changes the text that is stored in the encoder.
Represents a single TCP or UDP socket for input or output.
bool flush()
Sends the most recently queued TCP datagram(s) now.
Represents a network address to which UDP packets may be sent or to which a TCP socket may be bound...
int WaitForWrite(bool zeroFds, PN_uint32 sleep_time=0xffffffff)
This is the function that will wait till one of the sockets is ready for writing. ...