From ec362b2774263e985695cb57a6e3dbad395773c0 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 16 Feb 2018 09:37:31 +0800 Subject: [PATCH] For #464, query origin info and ip addresses --- trunk/src/app/srs_app_coworkers.cpp | 68 +++++++++++++++- trunk/src/app/srs_app_coworkers.hpp | 5 ++ trunk/src/service/srs_service_utility.cpp | 96 +++++++++++++++-------- 3 files changed, 137 insertions(+), 32 deletions(-) diff --git a/trunk/src/app/srs_app_coworkers.cpp b/trunk/src/app/srs_app_coworkers.cpp index 410c1ba67a..77787b46ed 100644 --- a/trunk/src/app/srs_app_coworkers.cpp +++ b/trunk/src/app/srs_app_coworkers.cpp @@ -27,6 +27,10 @@ using namespace std; #include #include +#include +#include +#include +#include SrsCoWorkers* SrsCoWorkers::_instance = NULL; @@ -36,6 +40,12 @@ SrsCoWorkers::SrsCoWorkers() SrsCoWorkers::~SrsCoWorkers() { + map::iterator it; + for (it = vhosts.begin(); it != vhosts.end(); ++it) { + SrsRequest* r = it->second; + srs_freep(r); + } + vhosts.clear(); } SrsCoWorkers* SrsCoWorkers::instance() @@ -48,16 +58,72 @@ SrsCoWorkers* SrsCoWorkers::instance() SrsJsonAny* SrsCoWorkers::dumps(string vhost, string app, string stream) { - return SrsJsonAny::null(); + SrsRequest* r = find_stream_info(vhost, app, stream); + if (!r) { + // TODO: FIXME: Find stream from our origin util return to the start point. + return SrsJsonAny::null(); + } + + vector& ips = srs_get_local_ips(); + if (ips.empty()) { + return SrsJsonAny::null(); + } + + SrsJsonArray* arr = SrsJsonAny::array(); + for (int i = 0; i < (int)ips.size(); i++) { + arr->append(SrsJsonAny::object() + ->set("ip", SrsJsonAny::str(ips.at(i).c_str())) + ->set("vhost", SrsJsonAny::str(r->vhost.c_str())) + ->set("self", SrsJsonAny::boolean(true))); + } + + return arr; +} + +SrsRequest* SrsCoWorkers::find_stream_info(string vhost, string app, string stream) +{ + // First, we should parse the vhost, if not exists, try default vhost instead. + SrsConfDirective* conf = _srs_config->get_vhost(vhost, true); + if (!conf) { + return NULL; + } + + // Get stream information from local cache. + string url = srs_generate_stream_url(conf->arg0(), app, stream); + map::iterator it = vhosts.find(url); + if (it == vhosts.end()) { + return NULL; + } + + return it->second; } srs_error_t SrsCoWorkers::on_publish(SrsSource* s, SrsRequest* r) { srs_error_t err = srs_success; + + string url = r->get_stream_url(); + + // Delete the previous stream informations. + map::iterator it = vhosts.find(url); + if (it != vhosts.end()) { + srs_freep(it->second); + } + + // Always use the latest one. + vhosts[url] = r->copy(); + return err; } void SrsCoWorkers::on_unpublish(SrsSource* s, SrsRequest* r) { + string url = r->get_stream_url(); + + map::iterator it = vhosts.find(url); + if (it != vhosts.end()) { + srs_freep(it->second); + vhosts.erase(it); + } } diff --git a/trunk/src/app/srs_app_coworkers.hpp b/trunk/src/app/srs_app_coworkers.hpp index fa7eff7142..55bb9e334d 100644 --- a/trunk/src/app/srs_app_coworkers.hpp +++ b/trunk/src/app/srs_app_coworkers.hpp @@ -27,6 +27,7 @@ #include #include +#include class SrsJsonAny; class SrsRequest; @@ -36,6 +37,8 @@ class SrsCoWorkers { private: static SrsCoWorkers* _instance; +private: + std::map vhosts; private: SrsCoWorkers(); virtual ~SrsCoWorkers(); @@ -43,6 +46,8 @@ class SrsCoWorkers static SrsCoWorkers* instance(); public: virtual SrsJsonAny* dumps(std::string vhost, std::string app, std::string stream); +private: + virtual SrsRequest* find_stream_info(std::string vhost, std::string app, std::string stream); public: virtual srs_error_t on_publish(SrsSource* s, SrsRequest* r); virtual void on_unpublish(SrsSource* s, SrsRequest* r); diff --git a/trunk/src/service/srs_service_utility.cpp b/trunk/src/service/srs_service_utility.cpp index 2e0bb3d06f..31f0827dbb 100644 --- a/trunk/src/service/srs_service_utility.cpp +++ b/trunk/src/service/srs_service_utility.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -100,6 +101,33 @@ bool srs_net_device_is_internet(const sockaddr* addr) vector _srs_system_ips; +void discover_network_iface(ifaddrs* cur, vector& ips, stringstream& ss0, stringstream& ss1, bool ipv6) +{ + char saddr[64]; + char* h = (char*)saddr; + socklen_t nbh = (socklen_t)sizeof(saddr); + const int r0 = getnameinfo(cur->ifa_addr, sizeof(sockaddr_storage), h, nbh, NULL, 0, NI_NUMERICHOST); + if(r0 != 0) { + srs_warn("convert local ip failed: %s", gai_strerror(r0)); + return; + } + + std::string ip(saddr, strlen(saddr)); + ss0 << ", iface[" << (int)ips.size() << "] " << cur->ifa_name << " " << (ipv6? "ipv6":"ipv4") + << " 0x" << std::hex << cur->ifa_flags << std::dec << " " << ip; + ips.push_back(ip); + + // set the device internet status. + if (!srs_net_device_is_internet(cur->ifa_addr)) { + ss1 << ", intranet "; + _srs_device_ifs[cur->ifa_name] = false; + } else { + ss1 << ", internet "; + _srs_device_ifs[cur->ifa_name] = true; + } + ss1 << cur->ifa_name << " " << ip; +} + void retrieve_local_ips() { vector& ips = _srs_system_ips; @@ -118,42 +146,48 @@ void retrieve_local_ips() stringstream ss1; ss1 << "devices"; - ifaddrs* p = ifap; - while (p != NULL) { + // Discover IPv4 first. + for (ifaddrs* p = ifap; p ; p = p->ifa_next) { ifaddrs* cur = p; - p = p->ifa_next; - // retrieve IP address - // ignore the tun0 network device, - // which addr is NULL. + // retrieve IP address, ignore the tun0 network device, whose addr is NULL. // @see: https://github.com/ossrs/srs/issues/141 - if ((cur->ifa_addr) && ((cur->ifa_addr->sa_family == AF_INET) || (cur->ifa_addr->sa_family == AF_INET6))) { - char saddr[64]; - char* h = (char*)saddr; - socklen_t nbh = (socklen_t)sizeof(saddr); - const int r0 = getnameinfo(cur->ifa_addr, sizeof(sockaddr_storage), h, nbh, NULL, 0, NI_NUMERICHOST); - if(r0 != 0) { - srs_warn("convert local ip failed: %s", gai_strerror(r0)); - break; - } - - std::string ip = saddr; - if (ip != SRS_CONSTS_LOCALHOST) { - ss0 << ", local[" << (int)ips.size() << "] ipv4 " << ip; - ips.push_back(ip); - } - - // set the device internet status. - if (!srs_net_device_is_internet(cur->ifa_addr)) { - ss1 << ", intranet "; - _srs_device_ifs[cur->ifa_name] = false; - } else { - ss1 << ", internet "; - _srs_device_ifs[cur->ifa_name] = true; - } - ss1 << cur->ifa_name << " " << ip; + bool ipv4 = (cur->ifa_addr->sa_family == AF_INET); + bool ready = (cur->ifa_flags & IFF_UP) && (cur->ifa_flags & IFF_RUNNING); + bool ignored = (!cur->ifa_addr) || (cur->ifa_flags & IFF_POINTOPOINT) || (cur->ifa_flags & IFF_PROMISC) || (cur->ifa_flags & IFF_LOOPBACK); + if (ipv4 && ready && !ignored) { + discover_network_iface(cur, ips, ss0, ss1, false); } } + + // Then, discover IPv6 addresses. + for (ifaddrs* p = ifap; p ; p = p->ifa_next) { + ifaddrs* cur = p; + + // retrieve IP address, ignore the tun0 network device, whose addr is NULL. + // @see: https://github.com/ossrs/srs/issues/141 + bool ipv6 = (cur->ifa_addr->sa_family == AF_INET6); + bool ready = (cur->ifa_flags & IFF_UP) && (cur->ifa_flags & IFF_RUNNING); + bool ignored = (!cur->ifa_addr) || (cur->ifa_flags & IFF_POINTOPOINT) || (cur->ifa_flags & IFF_PROMISC) || (cur->ifa_flags & IFF_LOOPBACK); + if (ipv6 && ready && !ignored) { + discover_network_iface(cur, ips, ss0, ss1, true); + } + } + + // If empty, disover IPv4 loopback. + for (ifaddrs* p = ifap; p ; p = p->ifa_next) { + ifaddrs* cur = p; + + // retrieve IP address, ignore the tun0 network device, whose addr is NULL. + // @see: https://github.com/ossrs/srs/issues/141 + bool ipv4 = (cur->ifa_addr->sa_family == AF_INET); + bool ready = (cur->ifa_flags & IFF_UP) && (cur->ifa_flags & IFF_RUNNING); + bool ignored = (!cur->ifa_addr) || (cur->ifa_flags & IFF_POINTOPOINT) || (cur->ifa_flags & IFF_PROMISC); + if (ipv4 && ready && !ignored) { + discover_network_iface(cur, ips, ss0, ss1, false); + } + } + srs_trace(ss0.str().c_str()); srs_trace(ss1.str().c_str());