void run () { uint16 raport = sConfig.GetIntDefault ("Ra.Port", 3443); std::string stringip = sConfig.GetStringDefault ("Ra.IP", "0.0.0.0"); ACE_INET_Addr listen_addr(raport, stringip.c_str()); if (m_Acceptor->open (listen_addr, m_Reactor, ACE_NONBLOCK) == -1) { sLog.outError ("MaNGOS RA can not bind to port %d on %s", raport, stringip.c_str ()); } sLog.outString ("Starting Remote access listner on port %d on %s", raport, stringip.c_str ()); while (!m_Reactor->reactor_event_loop_done()) { ACE_Time_Value interval (0, 10000); if (m_Reactor->run_reactor_event_loop (interval) == -1) break; if(World::IsStopped()) { m_Acceptor->close(); break; } } sLog.outString("RARunnable thread ended"); }
void RARunnable::run() { if (!sConfig->GetBoolDefault("Ra.Enable", false)) return; ACE_Acceptor<RASocket, ACE_SOCK_ACCEPTOR> acceptor; uint16 raport = sConfig->GetIntDefault("Ra.Port", 3443); std::string stringip = sConfig->GetStringDefault("Ra.IP", "0.0.0.0"); ACE_INET_Addr listen_addr(raport, stringip.c_str()); if (acceptor.open(listen_addr, m_Reactor) == -1) { sLog->outError("Trinity RA can not bind to port %d on %s", raport, stringip.c_str()); return; } sLog->outString("Starting Trinity RA on port %d on %s", raport, stringip.c_str()); while (!World::IsStopped()) { // don't be too smart to move this outside the loop // the run_reactor_event_loop will modify interval ACE_Time_Value interval(0, 100000); if (m_Reactor->run_reactor_event_loop(interval) == -1) break; } sLog->outStaticDebug("Trinity RA thread exiting"); }
/** \brief convert the object into a string */ std::string tcp_resp_t::to_string() const throw() { // handle the null case if( is_null() ) return "null"; // return the listen_addr_t in a string return listen_addr().to_string(); }
void RARunnable::run() { if (!ConfigMgr::GetBoolDefault("Ra.Enable", false)) return; ACE_Acceptor<RASocket, ACE_SOCK_ACCEPTOR> acceptor; uint16 raport = uint16(ConfigMgr::GetIntDefault("Ra.Port", 3443)); std::string stringip = ConfigMgr::GetStringDefault("Ra.IP", "0.0.0.0"); ACE_INET_Addr listen_addr(raport, stringip.c_str()); if (acceptor.open(listen_addr, m_Reactor) == -1) { TC_LOG_ERROR(LOG_FILTER_WORLDSERVER, "Trinity RA can not bind to port %d on %s", raport, stringip.c_str()); return; } TC_LOG_INFO(LOG_FILTER_WORLDSERVER, "Starting Trinity RA on port %d on %s", raport, stringip.c_str()); while (!World::IsStopped()) { // don't be too smart to move this outside the loop // the run_reactor_event_loop will modify interval ACE_Time_Value interval(0, 100000); if (m_Reactor->run_reactor_event_loop(interval) == -1) break; } TC_LOG_DEBUG(LOG_FILTER_WORLDSERVER, "Trinity RA thread exiting"); }
void SocketConnectorRunnable::run() { if (!ConfigMgr::GetBoolDefault("SocketConnector.Enable", false)) return; ACE_Acceptor<SocketConnector, ACE_SOCK_ACCEPTOR> acceptor; uint16 SocketConnectorPort = ConfigMgr::GetIntDefault("SocketConnector.Port", 3448); std::string stringip = ConfigMgr::GetStringDefault("SocketConnector.IP", "0.0.0.0"); ACE_INET_Addr listen_addr(SocketConnectorPort, stringip.c_str()); if (acceptor.open(listen_addr, m_Reactor) == -1) { sLog->outError(LOG_FILTER_WORLDSERVER, "Trinity Socket Connector can not bind to port %d on %s", SocketConnectorPort, stringip.c_str()); return; } sLog->outInfo(LOG_FILTER_WORLDSERVER, "Starting Trinity Socket Connector on port %d on %s", SocketConnectorPort, stringip.c_str()); while (!World::IsStopped()) { // don't be too smart to move this outside the loop // the run_reactor_event_loop will modify interval ACE_Time_Value interval(0, 100000); if (m_Reactor->run_reactor_event_loop(interval) == -1) break; } sLog->outDebug(LOG_FILTER_WORLDSERVER, "Trinity Socket Connector thread exiting"); }
/** \brief convert the object to a string */ std::string socket_resp_udp_t::to_string() const throw() { std::ostringstream oss; // build the string oss << "listening on " << listen_addr() << " in " << type(); // return the just built string return oss.str(); }
/** \brief set the callback */ socket_err_t socket_resp_udp_t::setup(const socket_type_t &p_socket_type , const socket_addr_t &p_listen_addr , socket_resp_vapi_cb_t *callback, void* userptr) throw() { // copy the parameter this->m_socket_type = p_socket_type; this->m_listen_addr = p_listen_addr; this->callback = callback; this->userptr = userptr; // copy the listen_addr DBG_ASSERT( domain() == listen_addr().get_domain() ); // return noerror return socket_err_t::OK; }
/** * Dump relayed or locally-emitted packet. * If ``from'' is NULL, packet was emitted locally. */ static void dump_packet_from_to(struct dump *dump, const struct gnutella_node *from, const struct gnutella_node *to, const pmsg_t *mb) { struct dump_header dh_to; struct dump_header dh_from; g_assert(to != NULL); g_assert(mb != NULL); g_assert(pmsg_read_base(mb) == pmsg_start(mb)); if (!dump_initialize(dump)) return; /* * This is only for Gnutella packets, leave DHT messages out. */ if (GTA_MSG_DHT == gnutella_header_get_function(pmsg_start(mb))) return; if (!ipset_contains_addr(&dump_tx_to_addrs, to->addr, TRUE)) return; if (NULL == from) { struct gnutella_node local; local.peermode = NODE_IS_UDP(to) ? NODE_P_UDP : NODE_P_NORMAL; local.addr = listen_addr(); local.port = GNET_PROPERTY(listen_port); if (!ipset_contains_addr(&dump_tx_from_addrs, local.addr, TRUE)) return; dump_header_set(&dh_from, &local); } else { if (!ipset_contains_addr(&dump_tx_from_addrs, from->addr, TRUE)) return; dump_header_set(&dh_from, from); } dump_header_set(&dh_to, to); dh_to.data[0] |= DH_F_TO; if (pmsg_prio(mb) != PMSG_P_DATA) dh_to.data[0] |= DH_F_CTRL; dump_append(dump, dh_to.data, sizeof dh_to.data); dump_append(dump, dh_from.data, sizeof dh_from.data); dump_append(dump, pmsg_read_base(mb), pmsg_size(mb)); dump_flush(dump); }
/** \brief Start the operation */ socket_err_t socket_resp_udp_t::start() throw() { inet_err_t inet_err; nlay_err_t nlay_err; // sanity check - the mandatory parameter MUST be set DBG_ASSERT( !listen_addr().is_null() ); DBG_ASSERT( !type().is_null() ); DBG_ASSERT( callback ); // sanity check - the profile MUST valid DBG_ASSERT( profile().check().succeed() ); // SETUP UDP_RESP_T udp_resp = nipmem_new udp_resp_t(); // get the listen address ipport_addr_t ipport_addr = socket_helper_udp_t::ipport_addr(listen_addr()); // start the udp_resp_t inet_err = udp_resp->start(ipport_addr, this, NULL); if( inet_err.failed() ) return socket_err_from_inet(inet_err, "Can't start udp_resp due to " ); // reread the listen_addr() once the responder is bound, in case of dynamic part m_listen_addr = socket_addr_t(domain().to_string() + "://" + udp_resp->get_listen_addr().to_string()); DBG_ASSERT( !listen_addr().is_null() ); // SETUP NLAY_RESP_T // start the nlay_resp_t socket_profile_udp_t & profile_dom = socket_profile_udp_t::from_socket(m_socket_profile); nlay_resp = nipmem_new nlay_resp_t(&profile_dom, type().to_nlay(), nlay_type_t::DGRAM); nlay_err = nlay_resp->start(); if( nlay_err.failed() ){ nipmem_zdelete udp_resp; return socket_err_from_nlay(nlay_err, "Can't start nlay_resp due to "); } // return no error return socket_err_t::OK; }
int WorldSocketMgr::StartReactiveIO (ACE_UINT16 port, const char* address) { m_UseNoDelay = sConfig->GetBoolDefault ("Network.TcpNodelay", true); int num_threads = sConfig->GetIntDefault ("Network.Threads", 1); if (num_threads <= 0) { sLog->outError ("Network.Threads is wrong in your config file"); return -1; } m_NetThreadsCount = static_cast<size_t> (num_threads + 1); m_NetThreads = new ReactorRunnable[m_NetThreadsCount]; sLog->outBasic ("Max allowed socket connections %d", ACE::max_handles()); // -1 means use default m_SockOutKBuff = sConfig->GetIntDefault ("Network.OutKBuff", -1); m_SockOutUBuff = sConfig->GetIntDefault ("Network.OutUBuff", 65536); if (m_SockOutUBuff <= 0) { sLog->outError ("Network.OutUBuff is wrong in your config file"); return -1; } WorldSocket::Acceptor *acc = new WorldSocket::Acceptor; m_Acceptor = acc; ACE_INET_Addr listen_addr (port, address); if (acc->open(listen_addr, m_NetThreads[0].GetReactor(), ACE_NONBLOCK) == -1) { sLog->outError ("Failed to open acceptor ,check if the port is free"); return -1; } for (size_t i = 0; i < m_NetThreadsCount; ++i) m_NetThreads[i].Start(); return 0; }
/** \brief convert the object into a string */ std::string udp_resp_t::to_string() const throw() { if( is_null() ) return "null"; return listen_addr().to_string(); }
/** \brief start the action */ inet_err_t udp_resp_t::start() throw() { struct sockaddr_in addr_in; std::string errstr; inet_err_t inet_err; // check the parameter DBG_ASSERT( !listen_addr().is_null() ); // create the socket int sock_fd = socket(AF_INET, SOCK_DGRAM, 0); if( sock_fd < 0 ){ errstr = "Cant create socket. errno=" + inet_oswarp_t::sock_strerror(); goto error; } // bind the socket (with no SO_REUSEADDR) addr_in = listen_addr().to_sockaddr_in(); if( bind(sock_fd, (struct sockaddr *)&addr_in, sizeof(addr_in)) ){ errstr = "cant bind socket to " + listen_addr().to_string() + " errno=" + inet_oswarp_t::sock_strerror(); goto close_socket; } // if the listen port was undefined, read the one assigned by the system if( listen_addr().port() == 0 ){ socklen_t addrlen = sizeof(addr_in); if( getsockname(sock_fd, (struct sockaddr *)&addr_in, &addrlen)){ errstr = "cant getsocketname errno=" + inet_oswarp_t::sock_strerror(); goto close_socket; } m_listen_addr = ipport_addr_t(addr_in); } // set this socket in non blocking for the connection inet_err = inet_oswarp_t::set_nonblock(sock_fd); if( inet_err.failed() ){ errstr = inet_err.to_string(); goto close_socket; } // if the local_ipport has a multicast ip address, join the multicast group if( listen_addr().ipaddr().is_multicast() ){ struct ip_mreq mreq; // describe the group mreq.imr_multiaddr.s_addr = htonl(listen_addr().ipaddr().get_v4_addr()); mreq.imr_interface.s_addr = htonl(INADDR_ANY); // do the IP_ADD_MEMBERSHIP inet_err = inet_oswarp_t::setsockopt(fdwatch->get_fd(), IPPROTO_IP , IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); if( inet_err.failed() ){ errstr = "cant ADD_MEMBERSHIP to socket " + listen_addr().to_string() + " due to " + inet_err.to_string(); goto close_socket; } } // some logging KLOG_DBG("udp_resp_t created on " << listen_addr()); // start the fdwatch fdwatch = nipmem_new fdwatch_t(); fdwatch->start(sock_fd, fdwatch_t::INPUT, this, NULL); // return no error return inet_err_t::OK; close_socket:; inet_oswarp_t::close_fd( sock_fd ); error:; return inet_err_t(inet_err_t::SYSTEM_ERR, errstr); }
/** * Displays assorted status information */ enum shell_reply shell_exec_status(struct gnutella_shell *sh, int argc, const char *argv[]) { const char *cur; const option_t options[] = { { "i", &cur }, }; int parsed; char buf[2048]; time_t now; shell_check(sh); g_assert(argv); g_assert(argc > 0); parsed = shell_options_parse(sh, argv, options, G_N_ELEMENTS(options)); if (parsed < 0) return REPLY_ERROR; argv += parsed; /* args[0] is first command argument */ argc -= parsed; /* counts only command arguments now */ now = tm_time(); /* Leading flags */ { char flags[47]; const char *fw; const char *fd; const char *pmp; const char *dht; /* * The flags are displayed as followed: * * UMP port mapping configured via UPnP * NMP port mapping configured via NAT-PMP * pmp port mapping available (UPnP or NAT-PMP), un-configured * CLK clock, GTKG expired * !FD or FD red or yellow bombs for fd shortage * STL upload stalls * gUL/yUL/rUL green, yellow or red upload early stalling levels * CPU cpu overloaded * MOV file moving * SHA SHA-1 rebuilding or verifying * TTH TTH rebuilding or verifying * LIB library rescan * :FW or FW indicates whether hole punching is possible * udp or UDP indicates UDP firewalling (lowercased for hole punching) * TCP indicates TCP-firewalled * - the happy face: no firewall * sDH/lDH/bDH seeded, own KUID looking or bootstrapping DHT * A or P active or passive DHT mode * UP or LF ultrapeer or leaf mode */ pmp = (GNET_PROPERTY(upnp_possible) || GNET_PROPERTY(natpmp_possible)) ? "pmp " : empty; if ( (GNET_PROPERTY(enable_upnp) || GNET_PROPERTY(enable_natpmp)) && GNET_PROPERTY(port_mapping_successful) ) { pmp = GNET_PROPERTY(enable_natpmp) ? "NMP " : "UMP "; } if (dht_enabled()) { dht = empty; switch ((enum dht_bootsteps) GNET_PROPERTY(dht_boot_status)) { case DHT_BOOT_NONE: case DHT_BOOT_SHUTDOWN: break; case DHT_BOOT_SEEDED: dht = "sDH "; break; case DHT_BOOT_OWN: dht = "lDH "; break; case DHT_BOOT_COMPLETING: dht = "bDH "; break; case DHT_BOOT_COMPLETED: dht = dht_is_active() ? "A " : "P "; break; case DHT_BOOT_MAX_VALUE: g_assert_not_reached(); } } else { dht = empty; } if (GNET_PROPERTY(is_firewalled) && GNET_PROPERTY(is_udp_firewalled)) { fw = GNET_PROPERTY(recv_solicited_udp) ? ":FW " : "FW "; } else if (GNET_PROPERTY(is_firewalled)) { fw = "TCP "; } else if (GNET_PROPERTY(is_udp_firewalled)) { fw = GNET_PROPERTY(recv_solicited_udp) ? "udp " : "UDP "; } else { fw = "- "; } if (GNET_PROPERTY(file_descriptor_runout)) { fd = "!FD "; } else if (GNET_PROPERTY(file_descriptor_shortage)) { fd = "FD "; } else { fd = empty; } gm_snprintf(flags, sizeof flags, "<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>", pmp, GNET_PROPERTY(download_queue_frozen) ? "DFZ " : empty, GNET_PROPERTY(ancient_version) ? "CLK " : empty, fd, GNET_PROPERTY(uploads_stalling) ? "STL " : empty, GNET_PROPERTY(uploads_bw_ignore_stolen) ? "gUL " : empty, GNET_PROPERTY(uploads_bw_uniform) ? "yUL " : empty, GNET_PROPERTY(uploads_bw_no_stealing) ? "rUL " : empty, GNET_PROPERTY(overloaded_cpu) ? "CPU " : empty, GNET_PROPERTY(file_moving) ? "MOV " : empty, (GNET_PROPERTY(sha1_rebuilding) || GNET_PROPERTY(sha1_verifying)) ? "SHA " : empty, (GNET_PROPERTY(tth_rebuilding) || GNET_PROPERTY(tth_verifying)) ? "TTH " : empty, GNET_PROPERTY(library_rebuilding) ? "LIB " : empty, fw, dht, settings_is_ultra() ? "UP" : "LF"); gm_snprintf(buf, sizeof buf, "+%s+\n" "| %-18s%51s |\n" "|%s|\n", dashes, "Status", flags, equals); shell_write(sh, buf); } /* General status */ { const char *blackout; short_string_t leaf_switch; short_string_t ultra_check; leaf_switch = timestamp_get_string( GNET_PROPERTY(node_last_ultra_leaf_switch)); ultra_check = timestamp_get_string( GNET_PROPERTY(node_last_ultra_check)); if (GNET_PROPERTY(is_firewalled) && GNET_PROPERTY(is_udp_firewalled)) { blackout = GNET_PROPERTY(recv_solicited_udp) ? "TCP,udp" : "TCP,UDP"; } else if (GNET_PROPERTY(is_firewalled)) { blackout = "TCP"; } else if (GNET_PROPERTY(is_udp_firewalled)) { blackout = GNET_PROPERTY(recv_solicited_udp) ? "udp" : "UDP"; } else { blackout = "None"; } gm_snprintf(buf, sizeof buf, "| Mode: %-9s Last Switch: %-19s%2s|\n" "| Uptime: %-9s Last Check: %-19s%2s|\n" "| Port: %-9u Blackout: %-7s%14s|\n" "|%s|\n", GNET_PROPERTY(online_mode) ? node_peermode_to_string(GNET_PROPERTY(current_peermode)) : "offline", GNET_PROPERTY(node_last_ultra_leaf_switch) ? leaf_switch.str : "never", space, short_time(delta_time(now, GNET_PROPERTY(start_stamp))), GNET_PROPERTY(node_last_ultra_check) ? ultra_check.str : "never", space, socket_listen_port(), blackout, space, equals); shell_write(sh, buf); } /* IPv4 info */ switch (GNET_PROPERTY(network_protocol)) { case NET_USE_BOTH: case NET_USE_IPV4: gm_snprintf(buf, sizeof buf, "| IPv4: %-44s Since: %-12s|\n", host_addr_to_string(listen_addr()), short_time(delta_time(now, GNET_PROPERTY(current_ip_stamp)))); shell_write(sh, buf); } /* IPv6 info */ switch (GNET_PROPERTY(network_protocol)) { case NET_USE_BOTH: gm_snprintf(buf, sizeof buf, "|%s|\n", dashes); shell_write(sh, buf); /* FALL THROUGH */ case NET_USE_IPV6: gm_snprintf(buf, sizeof buf, "| IPv6: %-44s Since: %-12s|\n", host_addr_to_string(listen_addr6()), short_time(delta_time(now, GNET_PROPERTY(current_ip6_stamp)))); shell_write(sh, buf); } /* Node counts */ gm_snprintf(buf, sizeof buf, "|%s|\n" "| Peers: %-7u Ultra %4u/%-7u Leaf %4u/%-6u Legacy %4u/%-4u |\n" "| Downloads %4u/%-4u Uploads %4u/%-7u Browse %4u/%-4u |\n" "|%s|\n", equals, GNET_PROPERTY(node_ultra_count) + GNET_PROPERTY(node_leaf_count) + GNET_PROPERTY(node_normal_count), GNET_PROPERTY(node_ultra_count), settings_is_ultra() ? GNET_PROPERTY(max_connections) : GNET_PROPERTY(max_ultrapeers), GNET_PROPERTY(node_leaf_count), GNET_PROPERTY(max_leaves), GNET_PROPERTY(node_normal_count), GNET_PROPERTY(normal_connections), GNET_PROPERTY(dl_active_count), GNET_PROPERTY(dl_running_count), GNET_PROPERTY(ul_running), GNET_PROPERTY(ul_registered), GNET_PROPERTY(html_browse_served) + GNET_PROPERTY(qhits_browse_served), GNET_PROPERTY(html_browse_count) + GNET_PROPERTY(qhits_browse_count), equals); shell_write(sh, buf); /* Bandwidths */ { const bool metric = GNET_PROPERTY(display_metric_units); short_string_t gnet_in, http_in, leaf_in, gnet_out, http_out, leaf_out; short_string_t dht_in, dht_out; gnet_bw_stats_t bw_stats, bw2_stats; const char *bwtype = cur ? "(cur)" : "(avg)"; gnet_get_bw_stats(BW_GNET_IN, &bw_stats); gnet_get_bw_stats(BW_GNET_UDP_IN, &bw2_stats); gnet_in = short_rate_get_string( cur ? bw_stats.current + bw2_stats.current : bw_stats.average + bw2_stats.average, metric); gnet_get_bw_stats(BW_GNET_OUT, &bw_stats); gnet_get_bw_stats(BW_GNET_UDP_OUT, &bw2_stats); gnet_out = short_rate_get_string( cur ? bw_stats.current + bw2_stats.current : bw_stats.average + bw2_stats.average, metric); gnet_get_bw_stats(BW_HTTP_IN, &bw_stats); http_in = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gnet_get_bw_stats(BW_HTTP_OUT, &bw_stats); http_out = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gnet_get_bw_stats(BW_LEAF_IN, &bw_stats); leaf_in = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gnet_get_bw_stats(BW_LEAF_OUT, &bw_stats); leaf_out = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gnet_get_bw_stats(BW_DHT_IN, &bw_stats); dht_in = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gnet_get_bw_stats(BW_DHT_OUT, &bw_stats); dht_out = short_rate_get_string( cur ? bw_stats.current : bw_stats.average, metric); gm_snprintf(buf, sizeof buf, "| %-70s|\n" "|%71s|\n" "| %5s In: %13s %13s %13s %13s |\n" "| %5s Out: %13s %13s %13s %13s |\n", "Bandwidth:" " Gnutella Leaf HTTP DHT", dashes, bwtype, gnet_in.str, leaf_in.str, http_in.str, dht_in.str, bwtype, gnet_out.str, leaf_out.str, http_out.str, dht_out.str); shell_write(sh, buf); } { char line[128]; bool metric = GNET_PROPERTY(display_metric_units); gm_snprintf(buf, sizeof buf, "|%s|\n", equals); shell_write(sh, buf); concat_strings(line, sizeof line, "Shares ", uint64_to_string(shared_files_scanned()), " file", shared_files_scanned() == 1 ? "" : "s", " ", short_kb_size(shared_kbytes_scanned(), metric), " total", (void *) 0); gm_snprintf(buf, sizeof buf, "| %-35s Up: %-11s Down: %-11s |\n", line, short_byte_size(GNET_PROPERTY(ul_byte_count), metric), short_byte_size2(GNET_PROPERTY(dl_byte_count), metric)); shell_write(sh, buf); gm_snprintf(buf, sizeof buf, "+%s+\n", dashes); shell_write(sh, buf); } return REPLY_READY; }
/** \brief start the action */ inet_err_t tcp_resp_t::start(const ipport_addr_t &p_listen_addr , tcp_resp_cb_t *callback, void *userptr) throw() { struct sockaddr_in addr_in; std::string errstr; inet_err_t inet_err; // copy some parameter this->m_listen_addr = p_listen_addr; this->callback = callback; this->userptr = userptr; // sanity check - the listen_addr MUST be non null DBG_ASSERT( !listen_addr().is_null() ); // create the socket int sock_fd = socket(AF_INET, SOCK_STREAM, 0); if( sock_fd < 0 ){ errstr = "Cant create socket. due to " + inet_oswarp_t::sock_strerror(); goto error; } // set REUSEADDR inet_err = inet_oswarp_t::set_reuseaddr(sock_fd); if( inet_err.failed() ){ errstr = "setsockopt SO_REUSEADDR failed due to " + inet_err.to_string(); goto close_socket; } // bind the socket addr_in = listen_addr().to_sockaddr_in(); if( bind(sock_fd, (struct sockaddr *)&addr_in, sizeof(addr_in)) ){ errstr = "cant bind socket to " + listen_addr().to_string() + " due to " + inet_oswarp_t::sock_strerror(); goto close_socket; } // if the listen port was undefined, read the one assigned by the system if( listen_addr().get_port() == 0 ){ socklen_t addrlen = sizeof(addr_in); if( getsockname(sock_fd, (struct sockaddr *)&addr_in, &addrlen)){ errstr = "cant getsocketname due to " + inet_oswarp_t::sock_strerror(); goto close_socket; } // convert the struct socketaddr_in into a ipport_addr_t m_listen_addr = ipport_addr_t(addr_in); } // set this socket in non blocking for the connection inet_err = inet_oswarp_t::set_nonblock(sock_fd); if( inet_err.failed() ){ errstr = inet_err.to_string(); goto close_socket; } // put the socket in listen mode if( listen(sock_fd, 64) < 0 ){ errstr = "cant cant listen on to " + listen_addr().to_string() + " due to " + inet_oswarp_t::sock_strerror(); goto close_socket; } // some logging KLOG_DBG("tcp_resp_t created on " << listen_addr); // start the fdwatch fdwatch = nipmem_new fdwatch_t(); fdwatch->start(sock_fd, fdwatch_t::INPUT, this, NULL); // return no error return inet_err_t::OK; // handle the error case close_socket:; inet_oswarp_t::close_fd( sock_fd ); error:; KLOG_INFO("errstr=" << errstr); return inet_err_t(inet_err_t::SYSTEM_ERR, errstr); }
/* * Find a server address that can be used by `caller' to contact * the local service specified by `serv_uaddr'. If `clnt_uaddr' is * non-NULL, it is used instead of `caller' as a hint suggesting * the best address (e.g. the `r_addr' field of an rpc, which * contains the rpcbind server address that the caller used). * * Returns the best server address as a malloc'd "universal address" * string which should be freed by the caller. On error, returns NULL. */ char * addrmerge(struct netbuf *caller, const char *serv_uaddr, const char *clnt_uaddr, const char *netid) { struct ifaddrs *ifap, *ifp = NULL, *bestif; struct netbuf *serv_nbp = NULL, *hint_nbp = NULL, tbuf; struct sockaddr *caller_sa, *hint_sa, *ifsa, *ifmasksa, *serv_sa; struct sockaddr_storage ss; struct netconfig *nconf; char *caller_uaddr = NULL; const char *hint_uaddr = NULL; char *ret = NULL; int bestif_goodness; #ifdef ND_DEBUG if (debugging) fprintf(stderr, "addrmerge(caller, %s, %s, %s\n", serv_uaddr, clnt_uaddr == NULL ? "NULL" : clnt_uaddr, netid); #endif caller_sa = caller->buf; if ((nconf = rpcbind_get_conf(netid)) == NULL) goto freeit; if ((caller_uaddr = taddr2uaddr(nconf, caller)) == NULL) goto freeit; /* * Use `clnt_uaddr' as the hint if non-NULL, but ignore it if its * address family is different from that of the caller. */ hint_sa = NULL; if (clnt_uaddr != NULL) { hint_uaddr = clnt_uaddr; if ((hint_nbp = uaddr2taddr(nconf, clnt_uaddr)) == NULL) goto freeit; hint_sa = hint_nbp->buf; } if (hint_sa == NULL || hint_sa->sa_family != caller_sa->sa_family) { hint_uaddr = caller_uaddr; hint_sa = caller->buf; } #ifdef ND_DEBUG if (debugging) fprintf(stderr, "addrmerge: hint %s\n", hint_uaddr); #endif /* Local caller, just return the server address. */ if (strncmp(caller_uaddr, "0.0.0.0.", 8) == 0 || strncmp(caller_uaddr, "::.", 3) == 0 || caller_uaddr[0] == '/') { ret = strdup(serv_uaddr); goto freeit; } if (getifaddrs(&ifp) < 0) goto freeit; /* * Loop through all interface addresses. We are listening to an address * if any of the following are true: * a) It's a loopback address * b) It was specified with the -h command line option * c) There were no -h command line options. * * Among addresses on which we are listening, choose in order of * preference an address that is: * * a) Equal to the hint * b) A link local address with the same scope ID as the client's * address, if the client's address is also link local * c) An address on the same subnet as the client's address * d) A non-localhost, non-p2p address * e) Any usable address */ bestif = NULL; bestif_goodness = 0; for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) { ifsa = ifap->ifa_addr; ifmasksa = ifap->ifa_netmask; /* Skip addresses where we don't listen */ if (ifsa == NULL || ifsa->sa_family != hint_sa->sa_family || !(ifap->ifa_flags & IFF_UP)) continue; if (!(ifap->ifa_flags & IFF_LOOPBACK) && !listen_addr(ifsa)) continue; if ((hint_sa->sa_family == AF_INET) && ((((struct sockaddr_in*)hint_sa)->sin_addr.s_addr == ((struct sockaddr_in*)ifsa)->sin_addr.s_addr))) { const int goodness = 4; bestif_goodness = goodness; bestif = ifap; goto found; } #ifdef INET6 if ((hint_sa->sa_family == AF_INET6) && (0 == memcmp(&((struct sockaddr_in6*)hint_sa)->sin6_addr, &((struct sockaddr_in6*)ifsa)->sin6_addr, sizeof(struct in6_addr))) && (((struct sockaddr_in6*)hint_sa)->sin6_scope_id == (((struct sockaddr_in6*)ifsa)->sin6_scope_id))) { const int goodness = 4; bestif_goodness = goodness; bestif = ifap; goto found; } if (hint_sa->sa_family == AF_INET6) { /* * For v6 link local addresses, if the caller is on * a link-local address then use the scope id to see * which one. */ if (IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(ifsa)) && IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(caller_sa)) && IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(hint_sa))) { if (SA2SIN6(ifsa)->sin6_scope_id == SA2SIN6(caller_sa)->sin6_scope_id) { const int goodness = 3; if (bestif_goodness < goodness) { bestif = ifap; bestif_goodness = goodness; } } } } #endif /* INET6 */ if (0 == bitmaskcmp(hint_sa, ifsa, ifmasksa)) { const int goodness = 2; if (bestif_goodness < goodness) { bestif = ifap; bestif_goodness = goodness; } } if (!(ifap->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) { const int goodness = 1; if (bestif_goodness < goodness) { bestif = ifap; bestif_goodness = goodness; } } if (bestif == NULL) bestif = ifap; } if (bestif == NULL) goto freeit; found: /* * Construct the new address using the address from * `bestif', and the port number from `serv_uaddr'. */ serv_nbp = uaddr2taddr(nconf, serv_uaddr); if (serv_nbp == NULL) goto freeit; serv_sa = serv_nbp->buf; memcpy(&ss, bestif->ifa_addr, bestif->ifa_addr->sa_len); switch (ss.ss_family) { case AF_INET: SA2SIN(&ss)->sin_port = SA2SIN(serv_sa)->sin_port; break; #ifdef INET6 case AF_INET6: SA2SIN6(&ss)->sin6_port = SA2SIN6(serv_sa)->sin6_port; break; #endif } tbuf.len = ss.ss_len; tbuf.maxlen = sizeof(ss); tbuf.buf = &ss; ret = taddr2uaddr(nconf, &tbuf); freeit: if (caller_uaddr != NULL) free(caller_uaddr); if (hint_nbp != NULL) { free(hint_nbp->buf); free(hint_nbp); } if (serv_nbp != NULL) { free(serv_nbp->buf); free(serv_nbp); } if (ifp != NULL) freeifaddrs(ifp); #ifdef ND_DEBUG if (debugging) fprintf(stderr, "addrmerge: returning %s\n", ret); #endif return ret; }
/*************** compatibility layer *******************************/ const ipport_addr_t & get_listen_addr()const throw() { return listen_addr(); }