Bug 825708 - Part 2: calculate priority using properties. r=ekr

This commit is contained in:
Patrick Wang 2013-08-28 15:27:14 +08:00
parent 2c7e7724c3
commit 1841b25eb6
13 changed files with 511 additions and 23 deletions

View File

@ -82,6 +82,7 @@ extern "C" {
#include "nricectx.h"
#include "nricemediastream.h"
#include "nr_socket_prsock.h"
#include "nrinterfaceprioritizer.h"
namespace mozilla {
@ -368,6 +369,20 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
return nullptr;
}
#ifdef USE_INTERFACE_PRIORITIZER
nr_interface_prioritizer *prioritizer = CreateInterfacePrioritizer();
if (!prioritizer) {
MOZ_MTLOG(PR_LOG_ERROR, "Couldn't create interface prioritizer.");
return nullptr;
}
r = nr_ice_ctx_set_interface_prioritizer(ctx->ctx_, prioritizer);
if (r) {
MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set interface prioritizer.");
return nullptr;
}
#endif // USE_INTERFACE_PRIORITIZER
// Create the handler objects
ctx->ice_handler_vtbl_ = new nr_ice_handler_vtbl();
ctx->ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair;

View File

@ -0,0 +1,189 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <map>
#include <set>
#include <string>
#include "logging.h"
#include "nrinterfaceprioritizer.h"
#include "nsCOMPtr.h"
MOZ_MTLOG_MODULE("mtransport")
namespace {
class LocalAddress {
public:
LocalAddress()
: key_(),
is_vpn_(-1),
estimated_speed_(-1),
type_preference_(-1) {}
bool Init(const nr_local_addr& local_addr) {
char buf[MAXIFNAME + 41];
int r = nr_transport_addr_fmt_ifname_addr_string(&local_addr.addr, buf, sizeof(buf));
if (r) {
MOZ_MTLOG(PR_LOG_ERROR, "Error formatting interface address string.");
return false;
}
key_ = buf;
is_vpn_ = (local_addr.interface.type & NR_INTERFACE_TYPE_VPN) != 0 ? 1 : 0;
estimated_speed_ = local_addr.interface.estimated_speed;
type_preference_ = GetNetworkTypePreference(local_addr.interface.type);
return true;
}
bool operator<(const LocalAddress& rhs) const {
// Interface that is "less" here is preferred.
// If type preferences are different, we should simply sort by
// |type_preference_|.
if (type_preference_ != rhs.type_preference_) {
return type_preference_ < rhs.type_preference_;
}
// If type preferences are the same, the next thing we use to sort is vpn.
// If two LocalAddress are different in |is_vpn_|, the LocalAddress that is
// not in vpn gets priority.
if (is_vpn_ != rhs.is_vpn_) {
return is_vpn_ < rhs.is_vpn_;
}
// Compare estimated speed.
if (estimated_speed_ != rhs.estimated_speed_) {
return estimated_speed_ > rhs.estimated_speed_;
}
// All things above are the same, we can at least sort with key.
return key_ < rhs.key_;
}
const std::string& GetKey() const {
return key_;
}
private:
// Getting the preference corresponding to a type. Getting lower number here
// means the type of network is preferred.
static inline int GetNetworkTypePreference(int type) {
if (type & NR_INTERFACE_TYPE_WIRED) {
return 1;
}
if (type & NR_INTERFACE_TYPE_WIFI) {
return 2;
}
if (type & NR_INTERFACE_TYPE_MOBILE) {
return 3;
}
return 4;
}
std::string key_;
int is_vpn_;
int estimated_speed_;
int type_preference_;
};
class InterfacePrioritizer {
public:
InterfacePrioritizer()
: local_addrs_(),
preference_map_(),
sorted_(false) {}
int add(const nr_local_addr *iface) {
LocalAddress addr;
if (!addr.Init(*iface)) {
return R_FAILED;
}
std::pair<std::set<LocalAddress>::iterator, bool> r =
local_addrs_.insert(addr);
if (!r.second) {
return R_ALREADY; // This address is already in the set.
}
sorted_ = false;
return 0;
}
int sort() {
UCHAR tmp_pref = 127;
preference_map_.clear();
for (std::set<LocalAddress>::iterator i = local_addrs_.begin();
i != local_addrs_.end(); ++i) {
if (tmp_pref == 0) {
return R_FAILED;
}
preference_map_.insert(make_pair(i->GetKey(), tmp_pref--));
}
sorted_ = true;
return 0;
}
int getPreference(const char *key, UCHAR *pref) {
if (!sorted_) {
return R_FAILED;
}
std::map<std::string, UCHAR>::iterator i = preference_map_.find(key);
if (i == preference_map_.end()) {
return R_NOT_FOUND;
}
*pref = i->second;
return 0;
}
private:
std::set<LocalAddress> local_addrs_;
std::map<std::string, UCHAR> preference_map_;
bool sorted_;
};
} // anonymous namespace
static int add_interface(void *obj, nr_local_addr *iface) {
InterfacePrioritizer *ip = static_cast<InterfacePrioritizer*>(obj);
return ip->add(iface);
}
static int get_priority(void *obj, const char *key, UCHAR *pref) {
InterfacePrioritizer *ip = static_cast<InterfacePrioritizer*>(obj);
return ip->getPreference(key, pref);
}
static int sort_preference(void *obj) {
InterfacePrioritizer *ip = static_cast<InterfacePrioritizer*>(obj);
return ip->sort();
}
static int destroy(void **objp) {
if (!objp || !*objp) {
return 0;
}
InterfacePrioritizer *ip = static_cast<InterfacePrioritizer*>(*objp);
*objp = 0;
delete ip;
return 0;
}
static nr_interface_prioritizer_vtbl priorizer_vtbl = {
add_interface,
get_priority,
sort_preference,
destroy
};
namespace mozilla {
nr_interface_prioritizer* CreateInterfacePrioritizer() {
nr_interface_prioritizer *ip;
int r = nr_interface_prioritizer_create_int(new InterfacePrioritizer(),
&priorizer_vtbl,
&ip);
if (r != 0) {
return nullptr;
}
return ip;
}
} // namespace mozilla

View File

@ -0,0 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nrinterfacepriority_h__
#define nrinterfacepriority_h__
extern "C" {
#include "nr_api.h"
#include "nr_interface_prioritizer.h"
}
namespace mozilla {
nr_interface_prioritizer* CreateInterfacePrioritizer();
} // namespace mozilla
#endif

View File

@ -40,7 +40,7 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/port/linux/include \
-I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/port/generic/include \
$(NULL)
DEFINES += -DLINUX
DEFINES += -DLINUX -DUSE_INTERFACE_PRIORITIZER
endif
ifeq ($(OS_TARGET), Android)
@ -71,6 +71,7 @@ MTRANSPORT_LCPPSRCS = \
nricemediastream.cpp \
nriceresolverfake.cpp \
nriceresolver.cpp \
nrinterfaceprioritizer.cpp \
nr_socket_prsock.cpp \
nr_timer.cpp \
transportflow.cpp \
@ -86,6 +87,7 @@ ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
MTRANSPORT_LCPPSRCS += \
gonk_addrs.cpp \
$(NULL)
DEFINES += -DUSE_INTERFACE_PRIORITIZER
endif
MTRANSPORT_CPPSRCS = $(addprefix $(topsrcdir)/media/mtransport/, $(MTRANSPORT_LCPPSRCS))

View File

@ -78,6 +78,8 @@
"./src/net/transport_addr_reg.h",
"./src/net/local_addr.c",
"./src/net/local_addr.h",
"./src/net/nr_interface_prioritizer.c",
"./src/net/nr_interface_prioritizer.h",
# STUN
"./src/stun/addrs.c",

View File

@ -358,23 +358,37 @@ int nr_ice_candidate_compute_priority(nr_ice_candidate *cand)
if(type_preference > 126)
r_log(LOG_ICE,LOG_ERR,"Illegal type preference %d",type_preference);
if(r=NR_reg_get2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,
&interface_preference)) {
if (r==R_NOT_FOUND) {
if (next_automatic_preference == 1) {
r_log(LOG_ICE,LOG_DEBUG,"Out of preference values. Can't assign one for interface %s",cand->base.ifname);
ABORT(R_NOT_FOUND);
if(!cand->ctx->interface_prioritizer) {
/* Prioritizer is not set, read from registry */
if(r=NR_reg_get2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,
&interface_preference)) {
if (r==R_NOT_FOUND) {
if (next_automatic_preference == 1) {
r_log(LOG_ICE,LOG_DEBUG,"Out of preference values. Can't assign one for interface %s",cand->base.ifname);
ABORT(R_NOT_FOUND);
}
r_log(LOG_ICE,LOG_DEBUG,"Automatically assigning preference for interface %s->%d",cand->base.ifname,
next_automatic_preference);
if (r=NR_reg_set2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,next_automatic_preference)){
ABORT(r);
}
interface_preference=next_automatic_preference;
next_automatic_preference--;
}
r_log(LOG_ICE,LOG_DEBUG,"Automatically assigning preference for interface %s->%d",cand->base.ifname,
next_automatic_preference);
if (r=NR_reg_set2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,next_automatic_preference)){
else {
ABORT(r);
}
interface_preference=next_automatic_preference;
next_automatic_preference--;
}
else {
}
else {
char key_of_interface[MAXIFNAME + 41];
if(r=nr_transport_addr_fmt_ifname_addr_string(&cand->base,key_of_interface,
sizeof(key_of_interface))) {
ABORT(r);
}
if(r=nr_interface_prioritizer_get_priority(cand->ctx->interface_prioritizer,
key_of_interface,&interface_preference)) {
ABORT(r);
}
}

View File

@ -170,31 +170,24 @@ int nr_ice_component_destroy(nr_ice_component **componentp)
return(0);
}
#define MAXADDRS 100 // Ridiculously high
/* Make all the candidates we can make at the beginning */
int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *component)
{
int r,_status;
nr_local_addr addrs[MAXADDRS];
nr_local_addr *addrs=ctx->local_addrs;
nr_socket *sock;
nr_ice_socket *isock=0;
nr_ice_candidate *cand=0;
char *lufrag;
char *lpwd;
Data pwd;
int addr_ct;
int addr_ct=ctx->local_addr_ct;
int i;
int j;
char label[256];
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): initializing component with id %d",ctx->label,component->component_id);
/* First, gather all the local addresses we have */
if(r=nr_stun_find_local_addresses(addrs,MAXADDRS,&addr_ct)) {
r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to find local addresses",ctx->label);
ABORT(r);
}
if(addr_ct==0){
r_log(LOG_ICE,LOG_ERR,"ICE(%s): no local addresses available",ctx->label);
ABORT(R_NOT_FOUND);

View File

@ -156,6 +156,33 @@ int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers,int
return(_status);
}
int nr_ice_ctx_set_local_addrs(nr_ice_ctx *ctx,nr_local_addr *addrs,int ct)
{
int _status,i,r;
if(ctx->local_addrs) {
RFREE(ctx->local_addrs);
ctx->local_addr_ct=0;
ctx->local_addrs=0;
}
if (ct) {
if(!(ctx->local_addrs=RCALLOC(sizeof(nr_local_addr)*ct)))
ABORT(R_NO_MEMORY);
for (i=0;i<ct;++i) {
if (r=nr_local_addr_copy(ctx->local_addrs+i,addrs+i)) {
ABORT(r);
}
}
ctx->local_addr_ct = ct;
}
_status=0;
abort:
return(_status);
}
int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver)
{
int _status;
@ -171,6 +198,20 @@ int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver)
return(_status);
}
int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *ip)
{
int _status;
if (ctx->interface_prioritizer) {
ABORT(R_ALREADY);
}
ctx->interface_prioritizer = ip;
_status=0;
abort:
return(_status);
}
#ifdef USE_TURN
int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out)
@ -301,6 +342,9 @@ int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
ctx->turn_server_ct=0;
#endif /* USE_TURN */
ctx->local_addrs=0;
ctx->local_addr_ct=0;
/* 255 is the max for our priority algorithm */
if((ctx->stun_server_ct+ctx->turn_server_ct)>255){
r_log(LOG_ICE,LOG_WARNING,"Too many STUN/TURN servers specified: max=255");
@ -348,6 +392,8 @@ static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
RFREE(ctx->stun_servers);
RFREE(ctx->local_addrs);
for (i = 0; i < ctx->turn_server_ct; i++) {
RFREE(ctx->turn_servers[i].username);
r_data_destroy(&ctx->turn_servers[i].password);
@ -374,6 +420,7 @@ static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
}
nr_resolver_destroy(&ctx->resolver);
nr_interface_prioritizer_destroy(&ctx->interface_prioritizer);
RFREE(ctx);
}
@ -416,10 +463,13 @@ void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg)
}
}
#define MAXADDRS 100 // Ridiculously high
int nr_ice_initialize(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
{
int r,_status;
nr_ice_media_stream *stream;
nr_local_addr addrs[MAXADDRS];
int i,addr_ct;
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Initializing candidates",ctx->label);
ctx->state=NR_ICE_STATE_INITIALIZING;
@ -431,6 +481,30 @@ int nr_ice_initialize(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
ABORT(R_BAD_ARGS);
}
/* First, gather all the local addresses we have */
if(r=nr_stun_find_local_addresses(addrs,MAXADDRS,&addr_ct)) {
r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to find local addresses",ctx->label);
ABORT(r);
}
/* Sort interfaces by preference */
if(ctx->interface_prioritizer) {
for(i=0;i<addr_ct;i++){
if(r=nr_interface_prioritizer_add_interface(ctx->interface_prioritizer,addrs+i)) {
r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to add interface ",ctx->label);
ABORT(r);
}
}
if(r=nr_interface_prioritizer_sort_preference(ctx->interface_prioritizer)) {
r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to sort interface by preference",ctx->label);
ABORT(r);
}
}
if (r=nr_ice_ctx_set_local_addrs(ctx,addrs,addr_ct)) {
ABORT(r);
}
/* Initialize all the media stream/component pairs */
stream=STAILQ_FIRST(&ctx->streams);
while(stream){

View File

@ -43,6 +43,7 @@ extern "C" {
#include "transport_addr.h"
#include "nr_socket.h"
#include "nr_resolver.h"
#include "nr_interface_prioritizer.h"
#include "stun_client_ctx.h"
#include "stun_server_ctx.h"
#include "turn_client_ctx.h"
@ -122,8 +123,11 @@ struct nr_ice_ctx_ {
int stun_server_ct;
nr_ice_turn_server *turn_servers; /* The list of turn servers */
int turn_server_ct;
nr_local_addr *local_addrs; /* The list of available local addresses and corresponding interface information */
int local_addr_ct;
nr_resolver *resolver; /* The resolver to use */
nr_interface_prioritizer *interface_prioritizer; /* Priority decision logic */
nr_ice_foundation_head foundations;
@ -161,6 +165,7 @@ int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx);
int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers, int ct);
int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers, int ct);
int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver);
int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *prioritizer);
extern int LOG_ICE;

View File

@ -0,0 +1,88 @@
/*
Copyright (c) 2007, Adobe Systems, Incorporated
Copyright (c) 2013, Mozilla
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "nr_api.h"
#include "nr_interface_prioritizer.h"
#include "transport_addr.h"
int nr_interface_prioritizer_create_int(void *obj,
nr_interface_prioritizer_vtbl *vtbl,nr_interface_prioritizer **ifpp)
{
int _status;
nr_interface_prioritizer *ifp=0;
if(!(ifp=RCALLOC(sizeof(nr_interface_prioritizer))))
ABORT(R_NO_MEMORY);
ifp->obj = obj;
ifp->vtbl = vtbl;
*ifpp = ifp;
_status=0;
abort:
return(_status);
}
int nr_interface_prioritizer_destroy(nr_interface_prioritizer **ifpp)
{
nr_interface_prioritizer *ifp;
if (!ifpp || !*ifpp)
return(0);
ifp = *ifpp;
*ifpp = 0;
ifp->vtbl->destroy(&ifp->obj);
RFREE(ifp);
return(0);
}
int nr_interface_prioritizer_add_interface(nr_interface_prioritizer *ifp,
nr_local_addr *addr)
{
return ifp->vtbl->add_interface(ifp->obj, addr);
}
int nr_interface_prioritizer_get_priority(nr_interface_prioritizer *ifp,
const char *key, UCHAR *interface_preference)
{
return ifp->vtbl->get_priority(ifp->obj,key,interface_preference);
}
int nr_interface_prioritizer_sort_preference(nr_interface_prioritizer *ifp)
{
return ifp->vtbl->sort_preference(ifp->obj);
}

View File

@ -0,0 +1,66 @@
/*
Copyright (c) 2007, Adobe Systems, Incorporated
Copyright (c) 2013, Mozilla
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _nr_interface_prioritizer
#define _nr_interface_prioritizer
#include "transport_addr.h"
#include "local_addr.h"
typedef struct nr_interface_prioritizer_vtbl_ {
int (*add_interface)(void *obj, nr_local_addr *iface);
int (*get_priority)(void *obj, const char *key, UCHAR *pref);
int (*sort_preference)(void *obj);
int (*destroy)(void **obj);
} nr_interface_prioritizer_vtbl;
typedef struct nr_interface_prioritizer_ {
void *obj;
nr_interface_prioritizer_vtbl *vtbl;
} nr_interface_prioritizer;
int nr_interface_prioritizer_create_int(void *obj, nr_interface_prioritizer_vtbl *vtbl,
nr_interface_prioritizer **prioritizer);
int nr_interface_prioritizer_destroy(nr_interface_prioritizer **prioritizer);
int nr_interface_prioritizer_add_interface(nr_interface_prioritizer *prioritizer,
nr_local_addr *addr);
int nr_interface_prioritizer_get_priority(nr_interface_prioritizer *prioritizer,
const char *key, UCHAR *interface_preference);
int nr_interface_prioritizer_sort_preference(nr_interface_prioritizer *prioritizer);
#endif

View File

@ -78,6 +78,27 @@ int nr_transport_addr_fmt_addr_string(nr_transport_addr *addr)
return(_status);
}
int nr_transport_addr_fmt_ifname_addr_string(const nr_transport_addr *addr, char *buf, int len)
{
int _status;
char buffer[40];
switch(addr->ip_version){
case NR_IPV4:
if (!inet_ntop(AF_INET, &addr->u.addr4.sin_addr,buffer,sizeof(buffer))) {
strncpy(buffer, "[error]", len);
}
snprintf(buf,len,"%s:%s",addr->ifname,buffer);
break;
default:
ABORT(R_INTERNAL);
}
_status=0;
abort:
return(_status);
}
int nr_sockaddr_to_transport_addr(struct sockaddr *saddr, int saddr_len, int protocol, int keep, nr_transport_addr *addr)
{
int r,_status;

View File

@ -91,6 +91,7 @@ int nr_transport_addr_is_loopback(nr_transport_addr *addr);
int nr_transport_addr_copy(nr_transport_addr *to, nr_transport_addr *from);
int nr_transport_addr_copy_keep_ifname(nr_transport_addr *to, nr_transport_addr *from);
int nr_transport_addr_fmt_addr_string(nr_transport_addr *addr);
int nr_transport_addr_fmt_ifname_addr_string(const nr_transport_addr *addr, char *buf, int len);
int nr_transport_addr_set_port(nr_transport_addr *addr, int port);
#endif