mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
2450 lines
79 KiB
Diff
2450 lines
79 KiB
Diff
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.c src/ice/ice_candidate.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.c 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_candidate.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -54,36 +54,38 @@
|
|
|
|
#include "stun_client_ctx.h"
|
|
#include "stun_server_ctx.h"
|
|
#include "turn_client_ctx.h"
|
|
#include "ice_ctx.h"
|
|
#include "ice_candidate.h"
|
|
#include "ice_reg.h"
|
|
#include "ice_util.h"
|
|
#include "nr_socket_turn.h"
|
|
|
|
+static int next_automatic_preference = 224;
|
|
+
|
|
static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand);
|
|
static int nr_ice_srvrflx_start_stun(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
|
|
-static void nr_ice_srvrflx_stun_finished_cb(int sock, int how, void *cb_arg);
|
|
+static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg);
|
|
#ifdef USE_TURN
|
|
static int nr_ice_start_relay_turn(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
|
|
-static void nr_ice_turn_allocated_cb(int sock, int how, void *cb_arg);
|
|
+static void nr_ice_turn_allocated_cb(NR_SOCKET sock, int how, void *cb_arg);
|
|
#endif /* USE_TURN */
|
|
|
|
char *nr_ice_candidate_type_names[]={0,"host","srflx","prflx","relay",0};
|
|
|
|
int nr_ice_candidate_create(nr_ice_ctx *ctx,char *label,nr_ice_component *comp,nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp)
|
|
{
|
|
nr_ice_candidate *cand=0;
|
|
nr_ice_candidate *tmp=0;
|
|
int r,_status;
|
|
-
|
|
+
|
|
if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
|
|
ABORT(R_NO_MEMORY);
|
|
if(!(cand->label=r_strdup(label)))
|
|
ABORT(R_NO_MEMORY);
|
|
cand->state=NR_ICE_CAND_STATE_CREATED;
|
|
cand->ctx=ctx;
|
|
cand->isock=isock;
|
|
cand->osock=osock;
|
|
cand->type=ctype;
|
|
cand->stun_server=stun_server;
|
|
@@ -189,21 +191,21 @@
|
|
if(cand->delay_timer)
|
|
NR_async_timer_cancel(cand->delay_timer);
|
|
|
|
RFREE(cand->foundation);
|
|
RFREE(cand->label);
|
|
RFREE(cand);
|
|
|
|
return(0);
|
|
}
|
|
|
|
-void nr_ice_candidate_destroy_cb(int s, int h, void *cb_arg)
|
|
+void nr_ice_candidate_destroy_cb(NR_SOCKET s, int h, void *cb_arg)
|
|
{
|
|
nr_ice_candidate *cand=cb_arg;
|
|
nr_ice_candidate_destroy(&cand);
|
|
}
|
|
|
|
/* This algorithm is not super-fast, but I don't think we need a hash
|
|
table just yet and it produces a small foundation string */
|
|
static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand)
|
|
{
|
|
nr_ice_foundation *foundation;
|
|
@@ -276,22 +278,38 @@
|
|
break;
|
|
default:
|
|
ABORT(R_INTERNAL);
|
|
}
|
|
|
|
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))
|
|
- ABORT(r);
|
|
+ &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--;
|
|
+ }
|
|
+ else {
|
|
+ ABORT(r);
|
|
+ }
|
|
+ }
|
|
|
|
cand->priority=
|
|
(type_preference << 24) |
|
|
(interface_preference << 16) |
|
|
(stun_priority << 8) |
|
|
(256 - cand->component_id);
|
|
|
|
/* S 4.1.2 */
|
|
assert(cand->priority>=1&&cand->priority<=2147483647);
|
|
|
|
@@ -306,21 +324,22 @@
|
|
|
|
cand->done_cb=ready_cb;
|
|
cand->cb_arg=cb_arg;
|
|
|
|
switch(cand->type){
|
|
case HOST:
|
|
if(r=nr_socket_getaddr(cand->isock->sock,&cand->addr))
|
|
ABORT(r);
|
|
cand->osock=cand->isock->sock;
|
|
cand->state=NR_ICE_CAND_STATE_INITIALIZED;
|
|
- ready_cb(0,0,cb_arg);
|
|
+ // Post this so that it doesn't happen in-line
|
|
+ NR_ASYNC_SCHEDULE(ready_cb,cb_arg);
|
|
break;
|
|
#ifdef USE_TURN
|
|
case RELAYED:
|
|
if(r=nr_ice_start_relay_turn(cand,ready_cb,cb_arg))
|
|
ABORT(r);
|
|
ABORT(R_WOULDBLOCK);
|
|
break;
|
|
#endif /* USE_TURN */
|
|
case SERVER_REFLEXIVE:
|
|
/* Need to start stun */
|
|
@@ -333,21 +352,21 @@
|
|
ABORT(R_INTERNAL);
|
|
}
|
|
|
|
_status=0;
|
|
abort:
|
|
if(_status && _status!=R_WOULDBLOCK)
|
|
cand->state=NR_ICE_CAND_STATE_FAILED;
|
|
return(_status);
|
|
}
|
|
|
|
-static void nr_ice_srvrflx_start_stun_timer_cb(int s, int how, void *cb_arg)
|
|
+static void nr_ice_srvrflx_start_stun_timer_cb(NR_SOCKET s, int how, void *cb_arg)
|
|
{
|
|
nr_ice_candidate *cand=cb_arg;
|
|
int r,_status;
|
|
|
|
cand->delay_timer=0;
|
|
|
|
/* TODO: if the response is a BINDING-ERROR-RESPONSE, then restart
|
|
* TODO: using NR_STUN_CLIENT_MODE_BINDING_REQUEST because the
|
|
* TODO: server may not have understood the 0.96-style request */
|
|
if(r=nr_stun_client_start(cand->u.srvrflx.stun, NR_STUN_CLIENT_MODE_BINDING_REQUEST_STUND_0_96, nr_ice_srvrflx_stun_finished_cb, cand))
|
|
@@ -387,21 +406,21 @@
|
|
|
|
_status=0;
|
|
abort:
|
|
if(_status){
|
|
cand->state=NR_ICE_CAND_STATE_FAILED;
|
|
}
|
|
return(_status);
|
|
}
|
|
|
|
#ifdef USE_TURN
|
|
-static void nr_ice_start_relay_turn_timer_cb(int s, int how, void *cb_arg)
|
|
+static void nr_ice_start_relay_turn_timer_cb(NR_SOCKET s, int how, void *cb_arg)
|
|
{
|
|
nr_ice_candidate *cand=cb_arg;
|
|
int r,_status;
|
|
int i;
|
|
|
|
cand->delay_timer=0;
|
|
|
|
if(r=nr_turn_client_allocate(cand->u.relayed.turn, cand->u.relayed.server->username, cand->u.relayed.server->password, cand->u.relayed.server->bandwidth_kbps, cand->u.relayed.server->lifetime_secs, nr_ice_turn_allocated_cb, cand))
|
|
ABORT(r);
|
|
|
|
@@ -443,21 +462,21 @@
|
|
|
|
_status=0;
|
|
abort:
|
|
if(_status){
|
|
cand->state=NR_ICE_CAND_STATE_FAILED;
|
|
}
|
|
return(_status);
|
|
}
|
|
#endif /* USE_TURN */
|
|
|
|
-static void nr_ice_srvrflx_stun_finished_cb(int sock, int how, void *cb_arg)
|
|
+static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg)
|
|
{
|
|
int _status;
|
|
nr_ice_candidate *cand=cb_arg;
|
|
|
|
/* Deregister to suppress duplicates */
|
|
if(cand->u.srvrflx.stun_handle){ /* This test because we might have failed before CB registered */
|
|
nr_ice_socket_deregister(cand->isock,cand->u.srvrflx.stun_handle);
|
|
cand->u.srvrflx.stun_handle=0;
|
|
}
|
|
|
|
@@ -481,40 +500,40 @@
|
|
}
|
|
_status = 0;
|
|
abort:
|
|
if(_status){
|
|
cand->state=NR_ICE_CAND_STATE_FAILED;
|
|
cand->done_cb(0,0,cand->cb_arg);
|
|
}
|
|
}
|
|
|
|
#ifdef USE_TURN
|
|
-static void nr_ice_turn_allocated_cb(int s, int how, void *cb_arg)
|
|
+static void nr_ice_turn_allocated_cb(NR_SOCKET s, int how, void *cb_arg)
|
|
{
|
|
int r,_status;
|
|
nr_ice_candidate *cand=cb_arg;
|
|
nr_turn_client_ctx *turn=cand->u.relayed.turn;
|
|
int i;
|
|
char *label;
|
|
|
|
/* Deregister to suppress duplicates */
|
|
if(cand->u.relayed.turn_handle){ /* This test because we might have failed before CB registered */
|
|
nr_ice_socket_deregister(cand->isock,cand->u.relayed.turn_handle);
|
|
cand->u.relayed.turn_handle=0;
|
|
}
|
|
|
|
switch(turn->state){
|
|
/* OK, we should have a mapped address */
|
|
case NR_TURN_CLIENT_STATE_ALLOCATED:
|
|
/* switch candidate from TURN mode to STUN mode */
|
|
|
|
- if(r=nr_concat_strings(&label,"turn-relay(",cand->base.as_string,"|",turn->relay_addr.as_string,")",0))
|
|
+ if(r=nr_concat_strings(&label,"turn-relay(",cand->base.as_string,"|",turn->relay_addr.as_string,")",NULL))
|
|
ABORT(r);
|
|
|
|
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Switching from TURN (%s) to RELAY (%s)",cand->u.relayed.turn->label,cand->label,label);
|
|
|
|
/* Copy out mapped address and relay address */
|
|
nr_transport_addr_copy(&turn->relay_addr, &cand->u.relayed.turn->stun_ctx[NR_TURN_CLIENT_PHASE_ALLOCATE_REQUEST2]->results.allocate_response2.relay_addr);
|
|
nr_transport_addr_copy(&cand->addr, &turn->relay_addr);
|
|
|
|
r_log(LOG_ICE,LOG_DEBUG,"ICE-CANDIDATE(%s): base=%s, candidate=%s", cand->label, cand->base.as_string, cand->addr.as_string);
|
|
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.h src/ice/ice_candidate.h
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.h 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_candidate.h 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -41,21 +41,22 @@
|
|
|
|
typedef enum {HOST=1, SERVER_REFLEXIVE, PEER_REFLEXIVE, RELAYED} nr_ice_candidate_type;
|
|
|
|
struct nr_ice_candidate_ {
|
|
char *label;
|
|
int state;
|
|
#define NR_ICE_CAND_STATE_CREATED 1
|
|
#define NR_ICE_CAND_STATE_INITIALIZING 2
|
|
#define NR_ICE_CAND_STATE_INITIALIZED 3
|
|
#define NR_ICE_CAND_STATE_FAILED 4
|
|
-#define NR_ICE_CAND_PEER_CANDIDATE 10
|
|
+#define NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED 9
|
|
+#define NR_ICE_CAND_PEER_CANDIDATE_PAIRED 10
|
|
struct nr_ice_ctx_ *ctx;
|
|
nr_ice_socket *isock; /* The socket to read from
|
|
(it contains all other candidates
|
|
on this socket) */
|
|
nr_socket *osock; /* The socket to write to */
|
|
nr_ice_media_stream *stream; /* The media stream this is associated with */
|
|
nr_ice_component *component; /* The component this is associated with */
|
|
nr_ice_candidate_type type; /* The type of the candidate (S 4.1.1) */
|
|
UCHAR component_id; /* The component id (S 4.1.2.1) */
|
|
nr_transport_addr addr; /* The advertised address;
|
|
@@ -89,21 +90,21 @@
|
|
TAILQ_ENTRY(nr_ice_candidate_) entry_comp;
|
|
};
|
|
|
|
extern char *nr_ice_candidate_type_names[];
|
|
|
|
|
|
int nr_ice_candidate_create(struct nr_ice_ctx_ *ctx,char *label, nr_ice_component *component, nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp);
|
|
int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
|
|
int nr_ice_candidate_process_stun(nr_ice_candidate *cand, UCHAR *msg, int len, nr_transport_addr *faddr);
|
|
int nr_ice_candidate_destroy(nr_ice_candidate **candp);
|
|
-void nr_ice_candidate_destroy_cb(int s, int h, void *cb_arg);
|
|
+void nr_ice_candidate_destroy_cb(NR_SOCKET s, int h, void *cb_arg);
|
|
int nr_ice_format_candidate_attribute(nr_ice_candidate *cand, char *attr, int maxlen);
|
|
int nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *attr,nr_ice_media_stream *stream,nr_ice_candidate **candp);
|
|
int nr_ice_peer_peer_rflx_candidate_create(nr_ice_ctx *ctx,char *label, nr_ice_component *comp,nr_transport_addr *addr, nr_ice_candidate **candp);
|
|
int nr_ice_candidate_compute_priority(nr_ice_candidate *cand);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
#endif
|
|
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.c src/ice/ice_candidate_pair.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.c 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_candidate_pair.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -37,21 +37,21 @@
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <nr_api.h>
|
|
#include "ice_ctx.h"
|
|
#include "ice_util.h"
|
|
#include "ice_codeword.h"
|
|
#include "stun.h"
|
|
|
|
static char *nr_ice_cand_pair_states[]={"UNKNOWN","FROZEN","WAITING","IN_PROGRESS","FAILED","SUCCEEDED","CANCELLED"};
|
|
|
|
-static void nr_ice_candidate_pair_restart_stun_controlled_cb(int s, int how, void *cb_arg);
|
|
+static void nr_ice_candidate_pair_restart_stun_controlled_cb(NR_SOCKET s, int how, void *cb_arg);
|
|
static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
|
|
nr_ice_candidate *lcand, nr_ice_candidate *rcand);
|
|
|
|
int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp)
|
|
{
|
|
nr_ice_cand_pair *pair=0;
|
|
UINT8 o_priority, a_priority;
|
|
char *lufrag,*rufrag;
|
|
char *lpwd,*rpwd;
|
|
char *l2ruser=0,*r2lpass=0;
|
|
@@ -61,21 +61,21 @@
|
|
UINT8 t_priority;
|
|
|
|
if(!(pair=RCALLOC(sizeof(nr_ice_cand_pair))))
|
|
ABORT(R_NO_MEMORY);
|
|
|
|
pair->pctx=pctx;
|
|
|
|
nr_ice_candidate_pair_compute_codeword(pair,lcand,rcand);
|
|
|
|
if(r=nr_concat_strings(&pair->as_string,pair->codeword,"|",lcand->addr.as_string,"|",
|
|
- rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",0))
|
|
+ rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")", NULL))
|
|
ABORT(r);
|
|
|
|
nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
|
|
pair->local=lcand;
|
|
pair->remote=rcand;
|
|
|
|
/* Priority computation S 5.7.2 */
|
|
if(pctx->ctx->flags & NR_ICE_CTX_FLAGS_OFFERER)
|
|
{
|
|
assert(!(pctx->ctx->flags & NR_ICE_CTX_FLAGS_ANSWERER));
|
|
@@ -87,21 +87,21 @@
|
|
o_priority=rcand->priority;
|
|
a_priority=lcand->priority;
|
|
}
|
|
pair->priority=(MIN(o_priority, a_priority))<<32 |
|
|
(MAX(o_priority, a_priority))<<1 | (o_priority > a_priority?0:1);
|
|
|
|
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Pairing candidate %s (%x):%s (%x) priority=%llu (%llx) codeword=%s",pctx->ctx->label,lcand->addr.as_string,lcand->priority,rcand->addr.as_string,rcand->priority,pair->priority,pair->priority,pair->codeword);
|
|
|
|
/* Foundation */
|
|
if(r=nr_concat_strings(&pair->foundation,lcand->foundation,"|",
|
|
- rcand->foundation,0))
|
|
+ rcand->foundation,NULL))
|
|
ABORT(r);
|
|
|
|
|
|
/* OK, now the STUN data */
|
|
lufrag=lcand->stream->ufrag?lcand->stream->ufrag:pctx->ctx->ufrag;
|
|
lpwd=lcand->stream->pwd?lcand->stream->pwd:pctx->ctx->pwd;
|
|
rufrag=rcand->stream->ufrag?rcand->stream->ufrag:pctx->peer_ufrag;
|
|
rpwd=rcand->stream->pwd?rcand->stream->pwd:pctx->peer_pwd;
|
|
|
|
|
|
@@ -110,39 +110,39 @@
|
|
|
|
/* Make a bogus candidate to compute a theoretical peer reflexive
|
|
* priority per S 7.1.1.1 */
|
|
memcpy(&tmpcand, lcand, sizeof(tmpcand));
|
|
tmpcand.type = PEER_REFLEXIVE;
|
|
if (r=nr_ice_candidate_compute_priority(&tmpcand))
|
|
ABORT(r);
|
|
t_priority = tmpcand.priority;
|
|
|
|
/* Our sending context */
|
|
- if(r=nr_concat_strings(&l2ruser,lufrag,":",rufrag,0))
|
|
+ if(r=nr_concat_strings(&l2ruser,lufrag,":",rufrag,NULL))
|
|
ABORT(r);
|
|
if(r=nr_stun_client_ctx_create(pair->as_string,
|
|
lcand->osock,
|
|
&rcand->addr,RTO,&pair->stun_client))
|
|
ABORT(r);
|
|
if(!(pair->stun_client->params.ice_binding_request.username=r_strdup(l2ruser)))
|
|
ABORT(R_NO_MEMORY);
|
|
if(r=r_data_make(&pair->stun_client->params.ice_binding_request.password,(UCHAR *)lpwd,strlen(lpwd)))
|
|
ABORT(r);
|
|
pair->stun_client->params.ice_binding_request.priority=t_priority;
|
|
pair->stun_client->params.ice_binding_request.control = pctx->controlling?
|
|
NR_ICE_CONTROLLING:NR_ICE_CONTROLLED;
|
|
|
|
pair->stun_client->params.ice_binding_request.tiebreaker=pctx->tiebreaker;
|
|
|
|
/* Our receiving username/passwords. Stash these for later
|
|
injection into the stun server ctx*/
|
|
- if(r=nr_concat_strings(&pair->r2l_user,rufrag,":",lufrag,0))
|
|
+ if(r=nr_concat_strings(&pair->r2l_user,rufrag,":",lufrag,NULL))
|
|
ABORT(r);
|
|
if(!(r2lpass=r_strdup(rpwd)))
|
|
ABORT(R_NO_MEMORY);
|
|
INIT_DATA(pair->r2l_pwd,(UCHAR *)r2lpass,strlen(r2lpass));
|
|
|
|
*pairp=pair;
|
|
|
|
_status=0;
|
|
abort:
|
|
RFREE(l2ruser);
|
|
@@ -178,21 +178,21 @@
|
|
|
|
int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
|
|
{
|
|
assert(pair->state==NR_ICE_PAIR_STATE_FROZEN);
|
|
|
|
nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING);
|
|
|
|
return(0);
|
|
}
|
|
|
|
-static void nr_ice_candidate_pair_stun_cb(int s, int how, void *cb_arg)
|
|
+static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg)
|
|
{
|
|
int r,_status;
|
|
nr_ice_cand_pair *pair=cb_arg,*orig_pair;
|
|
nr_ice_candidate *cand=0;
|
|
nr_stun_message *sres;
|
|
nr_transport_addr *request_src;
|
|
nr_transport_addr *request_dst;
|
|
nr_transport_addr *response_src;
|
|
nr_transport_addr response_dst;
|
|
nr_stun_message_attribute *attr;
|
|
@@ -457,32 +457,47 @@
|
|
abort:
|
|
return(_status);
|
|
}
|
|
|
|
int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state)
|
|
{
|
|
int r,_status;
|
|
|
|
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): setting pair %s to %s",
|
|
pctx->label,pair->as_string,nr_ice_cand_pair_states[state]);
|
|
- pair->state=state;
|
|
|
|
- if(pctx->state!=NR_ICE_PAIR_STATE_WAITING){
|
|
+ /* NOTE: This function used to reference pctx->state instead of
|
|
+ pair->state and the assignment to pair->state was at the top
|
|
+ of this function. Because pctx->state was never changed, this seems to have
|
|
+ been a typo. The natural logic is "if the state changed
|
|
+ decrement the counter" so this implies we should be checking
|
|
+ the pair state rather than the pctx->state.
|
|
+
|
|
+ This didn't cause big problems because waiting_pairs was only
|
|
+ used for pacing, so the pacing just was kind of broken.
|
|
+
|
|
+ This note is here as a reminder until we do more testing
|
|
+ and make sure that in fact this was a typo.
|
|
+ */
|
|
+ if(pair->state!=NR_ICE_PAIR_STATE_WAITING){
|
|
if(state==NR_ICE_PAIR_STATE_WAITING)
|
|
pctx->waiting_pairs++;
|
|
}
|
|
else{
|
|
if(state!=NR_ICE_PAIR_STATE_WAITING)
|
|
pctx->waiting_pairs--;
|
|
|
|
assert(pctx->waiting_pairs>=0);
|
|
}
|
|
+ pair->state=state;
|
|
+
|
|
+
|
|
if(pair->state==NR_ICE_PAIR_STATE_FAILED){
|
|
if(r=nr_ice_component_failed_pair(pair->remote->component, pair))
|
|
ABORT(r);
|
|
}
|
|
|
|
_status=0;
|
|
abort:
|
|
return(_status);
|
|
}
|
|
|
|
@@ -505,42 +520,42 @@
|
|
break;
|
|
}
|
|
|
|
c1=TAILQ_NEXT(c1,entry);
|
|
}
|
|
if(!c1) TAILQ_INSERT_TAIL(head,pair,entry);
|
|
|
|
return(0);
|
|
}
|
|
|
|
-void nr_ice_candidate_pair_restart_stun_nominated_cb(int s, int how, void *cb_arg)
|
|
+void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg)
|
|
{
|
|
nr_ice_cand_pair *pair=cb_arg;
|
|
int r,_status;
|
|
|
|
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s):%d: Restarting pair %s as nominated",pair->pctx->label,pair->local->stream->label,pair->remote->component->component_id,pair->as_string);
|
|
|
|
nr_stun_client_reset(pair->stun_client);
|
|
pair->stun_client->params.ice_binding_request.control=NR_ICE_CONTROLLING;
|
|
|
|
if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_USE_CANDIDATE,nr_ice_candidate_pair_stun_cb,pair))
|
|
ABORT(r);
|
|
|
|
if(r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request))
|
|
ABORT(r);
|
|
|
|
_status=0;
|
|
abort:
|
|
return;
|
|
}
|
|
|
|
-static void nr_ice_candidate_pair_restart_stun_controlled_cb(int s, int how, void *cb_arg)
|
|
+static void nr_ice_candidate_pair_restart_stun_controlled_cb(NR_SOCKET s, int how, void *cb_arg)
|
|
{
|
|
nr_ice_cand_pair *pair=cb_arg;
|
|
int r,_status;
|
|
|
|
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s):%d: Restarting pair %s as CONTROLLED",pair->pctx->label,pair->local->stream->label,pair->remote->component->component_id,pair->as_string);
|
|
|
|
nr_stun_client_reset(pair->stun_client);
|
|
pair->stun_client->params.ice_binding_request.control=NR_ICE_CONTROLLED;
|
|
|
|
if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_BINDING_REQUEST,nr_ice_candidate_pair_stun_cb,pair))
|
|
@@ -556,21 +571,21 @@
|
|
|
|
|
|
|
|
static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
|
|
nr_ice_candidate *lcand, nr_ice_candidate *rcand)
|
|
{
|
|
int r,_status;
|
|
char *as_string=0;
|
|
|
|
if(r=nr_concat_strings(&as_string,lcand->addr.as_string,"|",
|
|
- rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",0))
|
|
+ rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",NULL))
|
|
ABORT(r);
|
|
|
|
nr_ice_compute_codeword(as_string,strlen(as_string),pair->codeword);
|
|
|
|
_status=0;
|
|
abort:
|
|
RFREE(as_string);
|
|
return;
|
|
}
|
|
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.h src/ice/ice_candidate_pair.h
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.h 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_candidate_pair.h 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -72,18 +72,18 @@
|
|
|
|
int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp);
|
|
int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
|
|
int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
|
|
int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state);
|
|
int nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, FILE *out);
|
|
int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair);
|
|
int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair);
|
|
int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
|
|
int nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair);
|
|
-void nr_ice_candidate_pair_restart_stun_nominated_cb(int s, int how, void *cb_arg);
|
|
+void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg);
|
|
int nr_ice_candidate_pair_destroy(nr_ice_cand_pair **pairp);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
#endif
|
|
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_component.c src/ice/ice_component.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_component.c 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_component.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -451,21 +451,21 @@
|
|
if(r=nr_ice_peer_peer_rflx_candidate_create(comp->stream->pctx->ctx,"prflx",comp,&req->src_addr,&pcand)) {
|
|
*error=(r==R_NO_MEMORY)?500:400;
|
|
ABORT(r);
|
|
}
|
|
if(!nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_PRIORITY,&attr)){
|
|
r_log(LOG_ICE,LOG_ERR,"ICE-PEER(%s): Rejecting stun request without priority",comp->stream->pctx->label);
|
|
*error=487;
|
|
ABORT(R_BAD_DATA);
|
|
}
|
|
pcand->priority=attr->u.priority;
|
|
- pcand->state=NR_ICE_CAND_PEER_CANDIDATE;
|
|
+ pcand->state=NR_ICE_CAND_PEER_CANDIDATE_PAIRED;;
|
|
TAILQ_INSERT_TAIL(&comp->candidates,pcand,entry_comp);
|
|
|
|
if(r=nr_ice_candidate_pair_create(comp->stream->pctx,cand,pcand,
|
|
&pair)) {
|
|
*error=(r==R_NO_MEMORY)?500:400;
|
|
ABORT(r);
|
|
}
|
|
nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
|
|
|
|
if(r=nr_ice_candidate_pair_insert(&comp->stream->check_list,pair)) {
|
|
@@ -563,30 +563,38 @@
|
|
break;
|
|
}
|
|
|
|
/* PAIR with each peer*/
|
|
if(TAILQ_EMPTY(&pcomp->candidates)) {
|
|
/* can happen if our peer proposes no (or all bogus) candidates */
|
|
goto next_cand;
|
|
}
|
|
pcand=TAILQ_FIRST(&pcomp->candidates);
|
|
while(pcand){
|
|
- nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
|
|
- r_log(LOG_ICE,LOG_DEBUG,"Examining peer candidate %s:%s",codeword,pcand->label);
|
|
-
|
|
- if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
|
|
- ABORT(r);
|
|
-
|
|
- if(r=nr_ice_candidate_pair_insert(&pcomp->stream->check_list,
|
|
- pair))
|
|
- ABORT(r);
|
|
+ /* Only pair peer candidates which have not yet been paired.
|
|
+ This allows "trickle ICE". (Not yet standardized, but
|
|
+ part of WebRTC).
|
|
+
|
|
+ TODO(ekr@rtfm.com): Add refernece to the spec when there
|
|
+ is one.
|
|
+ */
|
|
+ if (pcand->state = NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED) {
|
|
+ nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
|
|
+ r_log(LOG_ICE,LOG_DEBUG,"Examining peer candidate %s:%s",codeword,pcand->label);
|
|
+
|
|
+ if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
|
|
+ ABORT(r);
|
|
|
|
+ if(r=nr_ice_candidate_pair_insert(&pcomp->stream->check_list,
|
|
+ pair))
|
|
+ ABORT(r);
|
|
+ }
|
|
pcand=TAILQ_NEXT(pcand,entry_comp);
|
|
}
|
|
|
|
if(!pair)
|
|
ABORT(R_INTERNAL);
|
|
|
|
/* Add the stun username/password pair from the last pair (any
|
|
would do) to the stun contexts */
|
|
isock=STAILQ_FIRST(&lcomp->sockets);
|
|
while(isock){
|
|
@@ -594,20 +602,28 @@
|
|
pair->r2l_user,&pair->r2l_pwd,nr_ice_component_stun_server_cb,pcomp))
|
|
ABORT(r);
|
|
|
|
isock=STAILQ_NEXT(isock,entry);
|
|
}
|
|
|
|
next_cand:
|
|
lcand=TAILQ_NEXT(lcand,entry_comp);
|
|
}
|
|
|
|
+ /* Mark all peer candidates as paired */
|
|
+ pcand=TAILQ_FIRST(&pcomp->candidates);
|
|
+ while(pcand){
|
|
+ pcand->state = NR_ICE_CAND_PEER_CANDIDATE_PAIRED;
|
|
+
|
|
+ pcand=TAILQ_NEXT(pcand,entry_comp);
|
|
+ }
|
|
+
|
|
_status=0;
|
|
abort:
|
|
return(_status);
|
|
}
|
|
|
|
int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair)
|
|
{
|
|
int r,_status;
|
|
int fire_cb=0;
|
|
nr_ice_cand_pair *p2;
|
|
@@ -616,32 +632,32 @@
|
|
fire_cb=1;
|
|
|
|
/* Are we changing what the nominated pair is? */
|
|
if(comp->nominated){
|
|
if(comp->nominated->priority > pair->priority)
|
|
return(0);
|
|
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): replacing pair %s with pair %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,comp->nominated->as_string,pair->as_string);
|
|
}
|
|
|
|
/* Set the new nominated pair */
|
|
- r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): nominated pair is %s (0x%x)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,(int)pair);
|
|
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): nominated pair is %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,pair);
|
|
comp->state=NR_ICE_COMPONENT_NOMINATED;
|
|
comp->nominated=pair;
|
|
comp->active=pair;
|
|
|
|
- r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling all pairs but %s (0x%x)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,(int)pair);
|
|
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling all pairs but %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,pair);
|
|
|
|
/* OK, we need to cancel off everything on this component */
|
|
p2=TAILQ_FIRST(&comp->stream->check_list);
|
|
while(p2){
|
|
if((p2 != pair) && (p2->remote->component->component_id == comp->component_id)){
|
|
- r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling pair %s (0x%x)",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->as_string,(int)p2);
|
|
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling pair %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->as_string,p2);
|
|
|
|
if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2))
|
|
ABORT(r);
|
|
}
|
|
|
|
p2=TAILQ_NEXT(p2,entry);
|
|
}
|
|
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling done",comp->stream->pctx->label,comp->stream->label,comp->component_id);
|
|
|
|
if(r=nr_ice_media_stream_component_nominated(comp->stream,comp))
|
|
@@ -734,21 +750,21 @@
|
|
ABORT(r);
|
|
}
|
|
|
|
_status=0;
|
|
abort:
|
|
RFREE(pairs);
|
|
return(_status);
|
|
}
|
|
|
|
|
|
-static void nr_ice_component_keepalive_cb(int s, int how, void *cb_arg)
|
|
+static void nr_ice_component_keepalive_cb(NR_SOCKET s, int how, void *cb_arg)
|
|
{
|
|
nr_ice_component *comp=cb_arg;
|
|
UINT4 keepalive_timeout;
|
|
|
|
assert(comp->keepalive_ctx);
|
|
|
|
if(NR_reg_get_uint4(NR_ICE_REG_KEEPALIVE_TIMER,&keepalive_timeout)){
|
|
keepalive_timeout=15000; /* Default */
|
|
}
|
|
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.c src/ice/ice_ctx.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.c 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_ctx.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -56,21 +56,21 @@
|
|
#include "util.h"
|
|
|
|
|
|
int LOG_ICE = 0;
|
|
|
|
static int nr_ice_random_string(char *str, int len);
|
|
static int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out);
|
|
#ifdef USE_TURN
|
|
static int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out);
|
|
#endif /* USE_TURN */
|
|
-static void nr_ice_ctx_destroy_cb(int s, int how, void *cb_arg);
|
|
+static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
|
|
|
|
int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
|
|
{
|
|
int r,_status;
|
|
nr_ice_stun_server *servers = 0;
|
|
int i;
|
|
NR_registry child;
|
|
char *addr=0;
|
|
UINT2 port;
|
|
in_addr_t addr_int;
|
|
@@ -271,21 +271,21 @@
|
|
*ctxp=ctx;
|
|
|
|
_status=0;
|
|
abort:
|
|
if(_status)
|
|
nr_ice_ctx_destroy_cb(0,0,ctx);
|
|
|
|
return(_status);
|
|
}
|
|
|
|
-static void nr_ice_ctx_destroy_cb(int s, int how, void *cb_arg)
|
|
+static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
|
|
{
|
|
nr_ice_ctx *ctx=cb_arg;
|
|
nr_ice_foundation *f1,*f2;
|
|
nr_ice_media_stream *s1,*s2;
|
|
int i;
|
|
nr_ice_stun_id *id1,*id2;
|
|
|
|
RFREE(ctx->label);
|
|
|
|
RFREE(ctx->stun_servers);
|
|
@@ -323,21 +323,21 @@
|
|
if(!ctxp || !*ctxp)
|
|
return(0);
|
|
|
|
NR_ASYNC_SCHEDULE(nr_ice_ctx_destroy_cb,*ctxp);
|
|
|
|
*ctxp=0;
|
|
|
|
return(0);
|
|
}
|
|
|
|
-void nr_ice_initialize_finished_cb(int s, int h, void *cb_arg)
|
|
+void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg)
|
|
{
|
|
nr_ice_ctx *ctx=cb_arg;
|
|
|
|
/* r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Candidate %s %s",ctx->label,
|
|
cand->label, cand->state==NR_ICE_CAND_STATE_INITIALIZED?"INITIALIZED":"FAILED");
|
|
*/
|
|
ctx->uninitialized_candidates--;
|
|
|
|
if(ctx->uninitialized_candidates==0){
|
|
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): All candidates initialized",ctx->label);
|
|
@@ -368,21 +368,22 @@
|
|
stream=STAILQ_FIRST(&ctx->streams);
|
|
while(stream){
|
|
if(r=nr_ice_media_stream_initialize(ctx,stream))
|
|
ABORT(r);
|
|
|
|
stream=STAILQ_NEXT(stream,entry);
|
|
}
|
|
|
|
if(ctx->uninitialized_candidates)
|
|
ABORT(R_WOULDBLOCK);
|
|
-
|
|
+
|
|
+
|
|
_status=0;
|
|
abort:
|
|
return(_status);
|
|
}
|
|
|
|
int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
|
|
{
|
|
int r,_status;
|
|
|
|
if(r=nr_ice_media_stream_create(ctx,label,components,streamp))
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.h src/ice/ice_ctx.h
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.h 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_ctx.h 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -92,23 +92,23 @@
|
|
UCHAR id[12];
|
|
|
|
STAILQ_ENTRY(nr_ice_stun_id_) entry;
|
|
} nr_ice_stun_id;
|
|
|
|
typedef STAILQ_HEAD(nr_ice_stun_id_head_,nr_ice_stun_id_) nr_ice_stun_id_head;
|
|
|
|
struct nr_ice_ctx_ {
|
|
UINT4 flags;
|
|
int state;
|
|
-#define NR_ICE_STATE_CREATED 1
|
|
-#define NR_ICE_STATE_INITIALIZING 2
|
|
-#define NR_ICE_STATE_INITIALIZED 3
|
|
+#define NR_ICE_STATE_CREATED 1
|
|
+#define NR_ICE_STATE_INITIALIZING 2
|
|
+#define NR_ICE_STATE_INITIALIZED 3
|
|
char *label;
|
|
|
|
char *ufrag;
|
|
char *pwd;
|
|
|
|
UINT4 Ta;
|
|
|
|
nr_ice_stun_server *stun_servers; /* The list of stun servers */
|
|
int stun_server_ct;
|
|
nr_ice_turn_server *turn_servers; /* The list of turn servers */
|
|
@@ -133,21 +133,21 @@
|
|
|
|
int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp);
|
|
#define NR_ICE_CTX_FLAGS_OFFERER 1
|
|
#define NR_ICE_CTX_FLAGS_ANSWERER (1<<1)
|
|
#define NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION (1<<2)
|
|
#define NR_ICE_CTX_FLAGS_LITE (1<<3)
|
|
|
|
int nr_ice_ctx_destroy(nr_ice_ctx **ctxp);
|
|
int nr_ice_initialize(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg);
|
|
int nr_ice_add_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand);
|
|
-void nr_ice_initialize_finished_cb(int s, int h, void *cb_arg);
|
|
+void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg);
|
|
int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp);
|
|
int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp);
|
|
int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
|
|
int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12]);
|
|
int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg);
|
|
int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx);
|
|
|
|
extern int LOG_ICE;
|
|
|
|
#ifdef __cplusplus
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.c src/ice/ice_media_stream.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.c 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_media_stream.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -35,21 +35,21 @@
|
|
static char *RCSSTRING __UNUSED__="$Id: ice_media_stream.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
|
|
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <nr_api.h>
|
|
#include <r_assoc.h>
|
|
#include <async_timer.h>
|
|
#include "ice_ctx.h"
|
|
|
|
static char *nr_ice_media_stream_states[]={"INVALID",
|
|
- "FROZEN","ACTIVE","COMPLETED","FAILED"
|
|
+ "UNPAIRED","FROZEN","ACTIVE","COMPLETED","FAILED"
|
|
};
|
|
|
|
int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
|
|
|
|
int nr_ice_media_stream_create(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
|
|
{
|
|
int r,_status;
|
|
nr_ice_media_stream *stream=0;
|
|
nr_ice_component *comp=0;
|
|
int i;
|
|
@@ -66,29 +66,29 @@
|
|
for(i=0;i<components;i++){
|
|
/* component-id must be > 0, so increment by 1 */
|
|
if(r=nr_ice_component_create(stream, i+1, &comp))
|
|
ABORT(r);
|
|
|
|
}
|
|
|
|
TAILQ_INIT(&stream->check_list);
|
|
|
|
stream->component_ct=components;
|
|
-
|
|
+ stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED;
|
|
*streamp=stream;
|
|
|
|
_status=0;
|
|
abort:
|
|
if(_status){
|
|
nr_ice_media_stream_destroy(&stream);
|
|
}
|
|
- return(_status);
|
|
+ return(_status);
|
|
}
|
|
|
|
int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp)
|
|
{
|
|
nr_ice_media_stream *stream;
|
|
nr_ice_component *c1,*c2;
|
|
nr_ice_cand_pair *p1,*p2;
|
|
if(!streamp || !*streamp)
|
|
return(0);
|
|
|
|
@@ -200,85 +200,148 @@
|
|
if(attrs){
|
|
for(index=0;index<attrct;index++){
|
|
RFREE(attrs[index]);
|
|
}
|
|
RFREE(attrs);
|
|
}
|
|
}
|
|
return(_status);
|
|
}
|
|
|
|
+
|
|
+/* Get a default candidate per 4.1.4 */
|
|
+int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp)
|
|
+ {
|
|
+ int _status;
|
|
+ nr_ice_component *comp;
|
|
+ nr_ice_candidate *cand;
|
|
+ nr_ice_candidate *best_cand = NULL;
|
|
+
|
|
+ comp=STAILQ_FIRST(&stream->components);
|
|
+ while(comp){
|
|
+ if (comp->component_id == component)
|
|
+ break;
|
|
+
|
|
+ comp=STAILQ_NEXT(comp,entry);
|
|
+ }
|
|
+
|
|
+ if (!comp)
|
|
+ ABORT(R_NOT_FOUND);
|
|
+
|
|
+ /* We have the component. Now find the "best" candidate, making
|
|
+ use of the fact that more "reliable" candidate types have
|
|
+ higher numbers. So, we sort by type and then priority within
|
|
+ type
|
|
+ */
|
|
+ cand=TAILQ_FIRST(&comp->candidates);
|
|
+ while(cand){
|
|
+ if (!best_cand) {
|
|
+ best_cand = cand;
|
|
+ }
|
|
+ else {
|
|
+ if (best_cand->type < cand->type) {
|
|
+ best_cand = cand;
|
|
+ } else if (best_cand->type == cand->type) {
|
|
+ if (best_cand->priority < cand->priority)
|
|
+ best_cand = cand;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ cand=TAILQ_NEXT(cand,entry_comp);
|
|
+ }
|
|
+
|
|
+ /* No candidates */
|
|
+ if (!best_cand)
|
|
+ ABORT(R_NOT_FOUND);
|
|
+
|
|
+ *candp = best_cand;
|
|
+
|
|
+ _status=0;
|
|
+ abort:
|
|
+ return(_status);
|
|
+ }
|
|
+
|
|
+
|
|
int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream)
|
|
{
|
|
int r,_status;
|
|
nr_ice_component *pcomp,*lcomp;
|
|
|
|
pcomp=STAILQ_FIRST(&pstream->components);
|
|
lcomp=STAILQ_FIRST(&lstream->components);
|
|
while(pcomp){
|
|
if(r=nr_ice_component_pair_candidates(pctx,lcomp,pcomp))
|
|
ABORT(r);
|
|
-
|
|
+
|
|
lcomp=STAILQ_NEXT(lcomp,entry);
|
|
pcomp=STAILQ_NEXT(pcomp,entry);
|
|
};
|
|
|
|
+ if (pstream->ice_state == NR_ICE_MEDIA_STREAM_UNPAIRED) {
|
|
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): unfreezing stream %s",pstream->pctx->label,pstream->label);
|
|
+ pstream->ice_state = NR_ICE_MEDIA_STREAM_CHECKS_FROZEN;
|
|
+ }
|
|
+
|
|
_status=0;
|
|
abort:
|
|
return(_status);
|
|
}
|
|
|
|
/* S 5.8 -- run the highest priority WAITING pair or if not available
|
|
FROZEN pair */
|
|
-static void nr_ice_media_stream_check_timer_cb(int s, int h, void *cb_arg)
|
|
+static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
|
|
{
|
|
int r,_status;
|
|
nr_ice_media_stream *stream=cb_arg;
|
|
nr_ice_cand_pair *pair;
|
|
int timer_val;
|
|
|
|
assert(stream->pctx->active_streams!=0);
|
|
|
|
timer_val=stream->pctx->ctx->Ta*stream->pctx->active_streams;
|
|
|
|
+ if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED) {
|
|
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): bogus state for stream %s",stream->pctx->label,stream->label);
|
|
+ }
|
|
assert(stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
|
|
|
|
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): check timer expired for media stream %s",stream->pctx->label,stream->label);
|
|
stream->timer=0;
|
|
|
|
-
|
|
/* Find the highest priority WAITING check and move it to RUNNING */
|
|
pair=TAILQ_FIRST(&stream->check_list);
|
|
while(pair){
|
|
if(pair->state==NR_ICE_PAIR_STATE_WAITING)
|
|
break;
|
|
pair=TAILQ_NEXT(pair,entry);
|
|
}
|
|
|
|
/* Hmmm... No WAITING. Let's look for FROZEN */
|
|
if(!pair){
|
|
pair=TAILQ_FIRST(&stream->check_list);
|
|
-
|
|
+
|
|
while(pair){
|
|
if(pair->state==NR_ICE_PAIR_STATE_FROZEN){
|
|
if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
|
|
ABORT(r);
|
|
break;
|
|
}
|
|
pair=TAILQ_NEXT(pair,entry);
|
|
}
|
|
}
|
|
|
|
if(pair){
|
|
nr_ice_candidate_pair_start(pair->pctx,pair); /* Ignore failures */
|
|
NR_ASYNC_TIMER_SET(timer_val,nr_ice_media_stream_check_timer_cb,cb_arg,&stream->timer);
|
|
}
|
|
+ /* TODO(ekr@rtfm.com): Report on the special case where there are no checks to
|
|
+ run at all */
|
|
_status=0;
|
|
abort:
|
|
return;
|
|
}
|
|
|
|
|
|
/* Start checks for this media stream (aka check list) */
|
|
int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
|
|
{
|
|
assert(stream->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FROZEN);
|
|
@@ -476,21 +539,23 @@
|
|
/* All done... */
|
|
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): all components have nominated candidate pairs",stream->pctx->label,stream->label);
|
|
nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
|
|
|
|
/* Cancel our timer */
|
|
if(stream->timer){
|
|
NR_async_timer_cancel(stream->timer);
|
|
stream->timer=0;
|
|
}
|
|
|
|
- stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream);
|
|
+ if (stream->pctx->handler) {
|
|
+ stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream);
|
|
+ }
|
|
|
|
/* Now tell the peer_ctx that we're done */
|
|
if(r=nr_ice_peer_ctx_stream_done(stream->pctx,stream))
|
|
ABORT(r);
|
|
|
|
done:
|
|
_status=0;
|
|
abort:
|
|
return(_status);
|
|
}
|
|
@@ -515,21 +580,23 @@
|
|
|
|
p2=TAILQ_NEXT(p2,entry);
|
|
}
|
|
|
|
/* Cancel our timer */
|
|
if(stream->timer){
|
|
NR_async_timer_cancel(stream->timer);
|
|
stream->timer=0;
|
|
}
|
|
|
|
- stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream);
|
|
+ if (stream->pctx->handler) {
|
|
+ stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream);
|
|
+ }
|
|
|
|
/* Now tell the peer_ctx that we're done */
|
|
if(r=nr_ice_peer_ctx_stream_done(stream->pctx,stream))
|
|
ABORT(r);
|
|
|
|
_status=0;
|
|
abort:
|
|
return(_status);
|
|
}
|
|
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.h src/ice/ice_media_stream.h
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.h 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_media_stream.h 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -45,40 +45,43 @@
|
|
struct nr_ice_peer_ctx_ *pctx;
|
|
|
|
struct nr_ice_media_stream_ *local_stream; /* used when this is a peer */
|
|
int component_ct;
|
|
nr_ice_component_head components;
|
|
|
|
char *ufrag; /* ICE username */
|
|
char *pwd; /* ICE password */
|
|
|
|
int ice_state;
|
|
-#define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN 1
|
|
-#define NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE 2
|
|
-#define NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED 3
|
|
-#define NR_ICE_MEDIA_STREAM_CHECKS_FAILED 4
|
|
+
|
|
+#define NR_ICE_MEDIA_STREAM_UNPAIRED 1
|
|
+#define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN 2
|
|
+#define NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE 3
|
|
+#define NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED 4
|
|
+#define NR_ICE_MEDIA_STREAM_CHECKS_FAILED 5
|
|
|
|
nr_ice_cand_pair_head check_list;
|
|
void *timer; /* Check list periodic timer */
|
|
|
|
// nr_ice_cand_pair_head valid_list;
|
|
-
|
|
+
|
|
STAILQ_ENTRY(nr_ice_media_stream_) entry;
|
|
};
|
|
|
|
typedef STAILQ_HEAD(nr_ice_media_stream_head_,nr_ice_media_stream_) nr_ice_media_stream_head;
|
|
|
|
int nr_ice_media_stream_create(struct nr_ice_ctx_ *ctx,char *label, int components, nr_ice_media_stream **streamp);
|
|
int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp);
|
|
int nr_ice_media_stream_finalize(nr_ice_media_stream *lstr,nr_ice_media_stream *rstr);
|
|
int nr_ice_media_stream_initialize(struct nr_ice_ctx_ *ctx, nr_ice_media_stream *stream);
|
|
int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp,int *attrctp);
|
|
+int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp);
|
|
int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream);
|
|
int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
|
|
int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
|
|
int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, char *foundation);
|
|
int nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream,FILE *out);
|
|
int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component);
|
|
int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component);
|
|
int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
|
|
int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int component, nr_ice_candidate **candp);
|
|
int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx,nr_ice_media_stream *str, int component, UCHAR *data, int len);
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_parser.c src/ice/ice_parser.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_parser.c 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_parser.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -35,20 +35,21 @@
|
|
static char *RCSSTRING __UNUSED__="$Id: ice_parser.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
|
|
|
|
#include <csi_platform.h>
|
|
#include <sys/types.h>
|
|
#ifdef WIN32
|
|
#include <winsock2.h>
|
|
#else
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
+#include <strings.h>
|
|
#endif
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include "nr_api.h"
|
|
#include "ice_ctx.h"
|
|
#include "ice_candidate.h"
|
|
#include "ice_reg.h"
|
|
|
|
static void
|
|
@@ -125,21 +126,21 @@
|
|
char *rel_addr=0;
|
|
|
|
if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
|
|
ABORT(R_NO_MEMORY);
|
|
|
|
if(!(cand->label=r_strdup(orig)))
|
|
ABORT(R_NO_MEMORY);
|
|
|
|
cand->ctx=ctx;
|
|
cand->isock=0;
|
|
- cand->state=NR_ICE_CAND_PEER_CANDIDATE;
|
|
+ cand->state=NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED;
|
|
cand->stream=stream;
|
|
skip_whitespace(&str);
|
|
|
|
/* Candidate attr */
|
|
if (strncasecmp(str, "candidate:", 10))
|
|
ABORT(R_BAD_DATA);
|
|
|
|
fast_forward(&str, 10);
|
|
if (*str == '\0')
|
|
ABORT(R_BAD_DATA);
|
|
@@ -311,26 +312,31 @@
|
|
/* it's expected to be at EOD at this point */
|
|
|
|
break;
|
|
default:
|
|
ABORT(R_INTERNAL);
|
|
break;
|
|
}
|
|
|
|
skip_whitespace(&str);
|
|
|
|
- assert(strlen(str) == 0);
|
|
-
|
|
+ /* This used to be an assert, but we don't want to exit on invalid
|
|
+ remote data */
|
|
+ if (strlen(str) != 0) {
|
|
+ ABORT(R_BAD_DATA);
|
|
+ }
|
|
+
|
|
*candp=cand;
|
|
|
|
_status=0;
|
|
abort:
|
|
+ /* TODO(ekr@rtfm.com): Fix memory leak if we have a parse error */
|
|
if (_status)
|
|
r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Error parsing attribute: %s",ctx->label,orig);
|
|
|
|
RFREE(connection_address);
|
|
RFREE(rel_addr);
|
|
return(_status);
|
|
}
|
|
|
|
|
|
int
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.c src/ice/ice_peer_ctx.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.c 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_peer_ctx.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -35,33 +35,35 @@
|
|
static char *RCSSTRING __UNUSED__="$Id: ice_peer_ctx.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
|
|
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <nr_api.h>
|
|
#include "ice_ctx.h"
|
|
#include "ice_peer_ctx.h"
|
|
#include "nr_crypto.h"
|
|
#include "async_timer.h"
|
|
|
|
-static void nr_ice_peer_ctx_destroy_cb(int s, int how, void *cb_arg);
|
|
+static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
|
|
+static int nr_ice_peer_ctx_parse_stream_attributes_int(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream *pstream, char **attrs, int attr_ct);
|
|
+static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate);
|
|
|
|
int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp)
|
|
{
|
|
int r,_status;
|
|
nr_ice_peer_ctx *pctx=0;
|
|
|
|
if(!(pctx=RCALLOC(sizeof(nr_ice_peer_ctx))))
|
|
ABORT(R_NO_MEMORY);
|
|
|
|
if(!(pctx->label=r_strdup(label)))
|
|
ABORT(R_NO_MEMORY);
|
|
-
|
|
+
|
|
pctx->ctx=ctx;
|
|
pctx->handler=handler;
|
|
|
|
/* Decide controlling vs. controlled */
|
|
if(ctx->flags & NR_ICE_CTX_FLAGS_LITE){
|
|
if(pctx->peer_lite){
|
|
r_log(LOG_ICE,LOG_ERR,"Both sides are ICE-Lite");
|
|
ABORT(R_BAD_DATA);
|
|
}
|
|
|
|
@@ -88,85 +90,177 @@
|
|
nr_ice_peer_ctx_destroy_cb(0,0,pctx);
|
|
}
|
|
return(_status);
|
|
}
|
|
|
|
|
|
|
|
int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct)
|
|
{
|
|
nr_ice_media_stream *pstream=0;
|
|
- nr_ice_candidate *cand=0;
|
|
nr_ice_component *comp,*comp2;
|
|
int r,_status;
|
|
- int i,j;
|
|
|
|
- /* Note: use component_ct from our own stream since components other
|
|
- than this offered by the other side are unusable */
|
|
+ /*
|
|
+ Note: use component_ct from our own stream since components other
|
|
+ than this offered by the other side are unusable */
|
|
if(r=nr_ice_media_stream_create(pctx->ctx,stream->label,stream->component_ct,&pstream))
|
|
ABORT(r);
|
|
-
|
|
- /* Match up the local and remote components */
|
|
+
|
|
+ /* Match up the local and remote components */
|
|
comp=STAILQ_FIRST(&stream->components);
|
|
comp2=STAILQ_FIRST(&pstream->components);
|
|
while(comp){
|
|
comp2->local_component=comp;
|
|
|
|
comp=STAILQ_NEXT(comp,entry);
|
|
comp2=STAILQ_NEXT(comp2,entry);
|
|
}
|
|
-
|
|
|
|
- pstream->ice_state=NR_ICE_MEDIA_STREAM_CHECKS_FROZEN;
|
|
pstream->local_stream=stream;
|
|
pstream->pctx=pctx;
|
|
|
|
+ if (r=nr_ice_peer_ctx_parse_stream_attributes_int(pctx,stream,pstream,attrs,attr_ct))
|
|
+ ABORT(r);
|
|
+
|
|
+
|
|
+ STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry);
|
|
+
|
|
+ _status=0;
|
|
+ abort:
|
|
+ return(_status);
|
|
+ }
|
|
+
|
|
+static int nr_ice_peer_ctx_parse_stream_attributes_int(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream *pstream, char **attrs, int attr_ct)
|
|
+ {
|
|
+ int r;
|
|
+ int i;
|
|
+
|
|
for(i=0;i<attr_ct;i++){
|
|
if(!strncmp(attrs[i],"ice-",4)){
|
|
- if(r=nr_ice_peer_ctx_parse_media_stream_attribute(pctx,pstream,attrs[i]))
|
|
+ if(r=nr_ice_peer_ctx_parse_media_stream_attribute(pctx,pstream,attrs[i])) {
|
|
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus ICE attribute",pctx->ctx->label,pctx->label);
|
|
continue;
|
|
- continue;
|
|
+ }
|
|
}
|
|
-
|
|
- if(r=nr_ice_peer_candidate_from_attribute(pctx->ctx,attrs[i],pstream,&cand))
|
|
- continue;
|
|
- if(cand->component_id-1>=pstream->component_ct){
|
|
- r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified too many components",pctx->ctx->label,pctx->label);
|
|
- continue;
|
|
+ else if (!strncmp(attrs[i],"candidate",9)){
|
|
+ if(r=nr_ice_ctx_parse_candidate(pctx,pstream,attrs[i])) {
|
|
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus candidate",pctx->ctx->label,pctx->label);
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus attribute",pctx->ctx->label,pctx->label);
|
|
}
|
|
+ }
|
|
|
|
- /* Not the fastest way to find a component, but it's what we got */
|
|
- j=1;
|
|
- for(comp=STAILQ_FIRST(&pstream->components);comp;comp=STAILQ_NEXT(comp,entry)){
|
|
- if(j==cand->component_id)
|
|
- break;
|
|
+ /* Doesn't fail because we just skip errors */
|
|
+ return(0);
|
|
+ }
|
|
|
|
- j++;
|
|
- }
|
|
-
|
|
- if(!comp){
|
|
- r_log(LOG_ICE,LOG_ERR,"Peer answered with more components than we offered");
|
|
- ABORT(R_BAD_DATA);
|
|
- }
|
|
-
|
|
- cand->component=comp;
|
|
+static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate)
|
|
+ {
|
|
+ nr_ice_candidate *cand=0;
|
|
+ nr_ice_component *comp;
|
|
+ int j;
|
|
+ int r, _status;
|
|
|
|
- TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
|
|
+ if(r=nr_ice_peer_candidate_from_attribute(pctx->ctx,candidate,pstream,&cand))
|
|
+ ABORT(r);
|
|
+ if(cand->component_id-1>=pstream->component_ct){
|
|
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified too many components",pctx->ctx->label,pctx->label);
|
|
+ ABORT(R_BAD_DATA);
|
|
}
|
|
|
|
- STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry);
|
|
+ /* Not the fastest way to find a component, but it's what we got */
|
|
+ j=1;
|
|
+ for(comp=STAILQ_FIRST(&pstream->components);comp;comp=STAILQ_NEXT(comp,entry)){
|
|
+ if(j==cand->component_id)
|
|
+ break;
|
|
+
|
|
+ j++;
|
|
+ }
|
|
+
|
|
+ if(!comp){
|
|
+ r_log(LOG_ICE,LOG_ERR,"Peer answered with more components than we offered");
|
|
+ ABORT(R_BAD_DATA);
|
|
+ }
|
|
+
|
|
+ cand->component=comp;
|
|
+
|
|
+ TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
|
|
|
|
_status=0;
|
|
- abort:
|
|
+ abort:
|
|
+ if (_status) {
|
|
+ nr_ice_candidate_destroy(&cand);
|
|
+ }
|
|
return(_status);
|
|
}
|
|
|
|
+
|
|
+
|
|
+int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *candidate)
|
|
+ {
|
|
+ /* First need to find the stream. Because we don't have forward pointers,
|
|
+ iterate through all the peer streams to find one that matches us */
|
|
+ nr_ice_media_stream *pstream;
|
|
+ int r,_status;
|
|
+ int needs_pairing = 0;
|
|
+
|
|
+ pstream=STAILQ_FIRST(&pctx->peer_streams);
|
|
+ while(pstream) {
|
|
+ if (pstream->local_stream == stream)
|
|
+ break;
|
|
+
|
|
+ pstream = STAILQ_NEXT(pstream, entry);
|
|
+ }
|
|
+ if (!pstream) {
|
|
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) has no stream matching stream %s",pctx->ctx->label,pctx->label,stream->label);
|
|
+ ABORT(R_NOT_FOUND);
|
|
+ }
|
|
+
|
|
+ switch(pstream->ice_state) {
|
|
+ case NR_ICE_MEDIA_STREAM_UNPAIRED:
|
|
+ break;
|
|
+ case NR_ICE_MEDIA_STREAM_CHECKS_FROZEN:
|
|
+ case NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE:
|
|
+ needs_pairing = 1;
|
|
+ break;
|
|
+ default:
|
|
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) tried to trickle ICE in inappropriate state %d",pctx->ctx->label,pctx->label,stream->label,pstream->ice_state);
|
|
+ ABORT(R_ALREADY);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if(r=nr_ice_ctx_parse_candidate(pctx,pstream,candidate)){
|
|
+ ABORT(r);
|
|
+ }
|
|
+
|
|
+ /* If ICE is running (i.e., we are in FROZEN or ACTIVE states)
|
|
+ then we need to pair this new candidate. For now we
|
|
+ just re-pair the stream which is inefficient but still
|
|
+ fine because we suppress duplicate pairing */
|
|
+ if (needs_pairing) {
|
|
+ if(r=nr_ice_media_stream_pair_candidates(pctx, stream, pstream)) {
|
|
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) failed to pair trickle ICE candidates",pctx->ctx->label,pctx->label,stream->label);
|
|
+ ABORT(r);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ _status =0;
|
|
+ abort:
|
|
+ return(_status);
|
|
+
|
|
+ }
|
|
+
|
|
+
|
|
int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx)
|
|
{
|
|
nr_ice_media_stream *stream;
|
|
int r,_status;
|
|
|
|
if(STAILQ_EMPTY(&pctx->peer_streams)) {
|
|
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) received no media stream attribributes",pctx->ctx->label,pctx->label);
|
|
ABORT(R_FAILED);
|
|
}
|
|
|
|
@@ -177,21 +271,21 @@
|
|
ABORT(r);
|
|
|
|
stream=STAILQ_NEXT(stream,entry);
|
|
}
|
|
|
|
_status=0;
|
|
abort:
|
|
return(_status);
|
|
}
|
|
|
|
-static void nr_ice_peer_ctx_destroy_cb(int s, int how, void *cb_arg)
|
|
+static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
|
|
{
|
|
nr_ice_peer_ctx *pctx=cb_arg;
|
|
nr_ice_media_stream *str1,*str2;
|
|
|
|
RFREE(pctx->label);
|
|
RFREE(pctx->peer_ufrag);
|
|
RFREE(pctx->peer_pwd);
|
|
|
|
STAILQ_FOREACH_SAFE(str1, &pctx->peer_streams, entry, str2){
|
|
STAILQ_REMOVE(&pctx->peer_streams,str1,nr_ice_media_stream_,entry);
|
|
@@ -199,44 +293,79 @@
|
|
}
|
|
|
|
RFREE(pctx);
|
|
}
|
|
|
|
int nr_ice_peer_ctx_destroy(nr_ice_peer_ctx **pctxp)
|
|
{
|
|
|
|
if(!pctxp || !*pctxp)
|
|
return(0);
|
|
-
|
|
+
|
|
+ /* Stop calling the handler */
|
|
+ (*pctxp)->handler = 0;
|
|
+
|
|
NR_ASYNC_SCHEDULE(nr_ice_peer_ctx_destroy_cb,*pctxp);
|
|
|
|
*pctxp=0;
|
|
|
|
return(0);
|
|
}
|
|
|
|
+
|
|
/* Start the checks for the first media stream (S 5.7)
|
|
The rest remain FROZEN */
|
|
int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx)
|
|
{
|
|
+ return nr_ice_peer_ctx_start_checks2(pctx, 0);
|
|
+ }
|
|
+
|
|
+/* Start checks for some media stream.
|
|
+
|
|
+ If allow_non_first == 0, then we only look at the first stream,
|
|
+ which is 5245-complaint.
|
|
+
|
|
+ If allow_non_first == 1 then we find the first non-empty stream
|
|
+ This is not compliant with RFC 5245 but is necessary to make trickle ICE
|
|
+ work plausibly
|
|
+*/
|
|
+int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first)
|
|
+ {
|
|
int r,_status;
|
|
nr_ice_media_stream *stream;
|
|
|
|
stream=STAILQ_FIRST(&pctx->peer_streams);
|
|
if(!stream)
|
|
ABORT(R_FAILED);
|
|
|
|
+ while (stream) {
|
|
+ if(!TAILQ_EMPTY(&stream->check_list))
|
|
+ break;
|
|
+
|
|
+ if(!allow_non_first){
|
|
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) first stream has empty check list",pctx->ctx->label,pctx->label);
|
|
+ ABORT(R_FAILED);
|
|
+ }
|
|
+
|
|
+ stream=STAILQ_NEXT(stream, entry);
|
|
+ }
|
|
+
|
|
+ if (!stream) {
|
|
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) no streams with non-empty check lists",pctx->ctx->label,pctx->label);
|
|
+ ABORT(R_NOT_FOUND);
|
|
+ }
|
|
+
|
|
if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN) {
|
|
- if(r=nr_ice_media_stream_unfreeze_pairs(pctx,stream))
|
|
- ABORT(r);
|
|
- if(r=nr_ice_media_stream_start_checks(pctx,stream))
|
|
- ABORT(r);
|
|
+ if(r=nr_ice_media_stream_unfreeze_pairs(pctx,stream))
|
|
+ ABORT(r);
|
|
+ if(r=nr_ice_media_stream_start_checks(pctx,stream))
|
|
+ ABORT(r);
|
|
}
|
|
|
|
_status=0;
|
|
abort:
|
|
return(_status);
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out)
|
|
{
|
|
@@ -253,26 +382,28 @@
|
|
stream=STAILQ_NEXT(stream,entry);
|
|
}
|
|
fprintf(out,"==========================================\n");
|
|
|
|
_status=0;
|
|
abort:
|
|
return(_status);
|
|
}
|
|
#endif
|
|
|
|
-static void nr_ice_peer_ctx_fire_done(int s, int how, void *cb_arg)
|
|
+static void nr_ice_peer_ctx_fire_done(NR_SOCKET s, int how, void *cb_arg)
|
|
{
|
|
nr_ice_peer_ctx *pctx=cb_arg;
|
|
|
|
/* Fire the handler callback to say we're done */
|
|
- pctx->handler->vtbl->ice_completed(pctx->handler->obj, pctx);
|
|
+ if (pctx->handler) {
|
|
+ pctx->handler->vtbl->ice_completed(pctx->handler->obj, pctx);
|
|
+ }
|
|
}
|
|
|
|
|
|
/* OK, a stream just went ready. Examine all the streams to see if we're
|
|
maybe miraculously done */
|
|
int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
|
|
{
|
|
int _status;
|
|
nr_ice_media_stream *str;
|
|
int failed=0;
|
|
@@ -365,21 +496,24 @@
|
|
NR_TRANSPORT_ADDR_CMP_MODE_ALL))
|
|
break;
|
|
|
|
cand=TAILQ_NEXT(cand,entry_comp);
|
|
}
|
|
|
|
if(!cand)
|
|
ABORT(R_REJECTED);
|
|
|
|
/* OK, there's a match. Call the handler */
|
|
- r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Delivering data", pctx->label);
|
|
|
|
- pctx->handler->vtbl->msg_recvd(pctx->handler->obj,
|
|
- pctx,comp->stream,comp->component_id,data,len);
|
|
+ if (pctx->handler) {
|
|
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Delivering data", pctx->label);
|
|
+
|
|
+ pctx->handler->vtbl->msg_recvd(pctx->handler->obj,
|
|
+ pctx,comp->stream,comp->component_id,data,len);
|
|
+ }
|
|
|
|
_status=0;
|
|
abort:
|
|
return(_status);
|
|
}
|
|
|
|
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.h src/ice/ice_peer_ctx.h
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.h 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_peer_ctx.h 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -33,23 +33,21 @@
|
|
|
|
|
|
#ifndef _ice_peer_ctx_h
|
|
#define _ice_peer_ctx_h
|
|
#ifdef __cplusplus
|
|
using namespace std;
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
struct nr_ice_peer_ctx_ {
|
|
- int state;
|
|
char *label;
|
|
-
|
|
nr_ice_ctx *ctx;
|
|
nr_ice_handler *handler;
|
|
|
|
UCHAR controlling; /* 1 for controlling, 0 for controlled */
|
|
UINT8 tiebreaker;
|
|
|
|
char *peer_ufrag;
|
|
char *peer_pwd;
|
|
int peer_lite;
|
|
int peer_ice_mismatch;
|
|
@@ -59,23 +57,26 @@
|
|
int waiting_pairs;
|
|
|
|
STAILQ_ENTRY(nr_ice_peer_ctx_) entry;
|
|
};
|
|
|
|
typedef STAILQ_HEAD(nr_ice_peer_ctx_head_, nr_ice_peer_ctx_) nr_ice_peer_ctx_head;
|
|
|
|
int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp);
|
|
int nr_ice_peer_ctx_destroy(nr_ice_peer_ctx **pctxp);
|
|
int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct);
|
|
+int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *cand);
|
|
+
|
|
int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx);
|
|
int nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int attr_ct);
|
|
int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx);
|
|
+int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first);
|
|
int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out);
|
|
int nr_ice_peer_ctx_log_state(nr_ice_peer_ctx *pctx);
|
|
int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
|
|
int nr_ice_peer_ctx_find_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component_id, nr_ice_component **compp);
|
|
int nr_ice_peer_ctx_deliver_packet_maybe(nr_ice_peer_ctx *pctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
#endif
|
|
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_socket.c src/ice/ice_socket.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_socket.c 2012-09-16 16:26:08.000000000 -0700
|
|
+++ src/ice/ice_socket.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -216,28 +216,34 @@
|
|
RFREE(s1);
|
|
}
|
|
|
|
RFREE(isock);
|
|
|
|
return(0);
|
|
}
|
|
|
|
int nr_ice_socket_close(nr_ice_socket *isock)
|
|
{
|
|
+#ifdef NR_SOCKET_IS_VOID_PTR
|
|
+ NR_SOCKET fd=NULL;
|
|
+ NR_SOCKET no_socket = NULL;
|
|
+#else
|
|
NR_SOCKET fd=-1;
|
|
+ NR_SOCKET no_socket = -1;
|
|
+#endif
|
|
|
|
if (!isock||!isock->sock)
|
|
return(0);
|
|
|
|
nr_socket_getfd(isock->sock,&fd);
|
|
assert(isock->sock!=0);
|
|
- if(fd!=-1){
|
|
+ if(fd != no_socket){
|
|
NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_READ);
|
|
NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_WRITE);
|
|
nr_socket_destroy(&isock->sock);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
int nr_ice_socket_register_stun_client(nr_ice_socket *sock, nr_stun_client_ctx *srv,void **handle)
|
|
{
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/net/nr_socket.h src/net/nr_socket.h
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/net/nr_socket.h 2012-09-16 16:26:09.000000000 -0700
|
|
+++ src/net/nr_socket.h 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -38,21 +38,23 @@
|
|
#include <sys/types.h>
|
|
#ifdef WIN32
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
#else
|
|
#include <sys/socket.h>
|
|
#endif
|
|
|
|
#include "transport_addr.h"
|
|
|
|
-#ifdef WIN32
|
|
+#ifdef __cplusplus
|
|
+#define restrict
|
|
+#elif defined(WIN32)
|
|
#define restrict __restrict
|
|
#endif
|
|
|
|
typedef struct nr_socket_vtbl_ {
|
|
int (*destroy)(void **obj);
|
|
int (*ssendto)(void *obj,const void *msg, size_t len, int flags,
|
|
nr_transport_addr *addr);
|
|
int (*srecvfrom)(void *obj,void * restrict buf, size_t maxlen, size_t *len, int flags,
|
|
nr_transport_addr *addr);
|
|
int (*getfd)(void *obj, NR_SOCKET *fd);
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/net/transport_addr_reg.c src/net/transport_addr_reg.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/net/transport_addr_reg.c 2012-09-16 16:26:09.000000000 -0700
|
|
+++ src/net/transport_addr_reg.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -29,25 +29,27 @@
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
|
|
|
|
static char *RCSSTRING __UNUSED__="$Id: transport_addr_reg.c,v 1.2 2008/04/28 17:59:03 ekr Exp $";
|
|
|
|
#include <csi_platform.h>
|
|
#include <stdio.h>
|
|
+#include <string.h>
|
|
#include <memory.h>
|
|
#include <sys/types.h>
|
|
#ifdef WIN32
|
|
#include <winsock2.h>
|
|
#else
|
|
+#include <strings.h>
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#endif
|
|
#include <assert.h>
|
|
#include "nr_api.h"
|
|
#include "transport_addr.h"
|
|
#include "transport_addr_reg.h"
|
|
|
|
@@ -83,20 +85,22 @@
|
|
|
|
if ((r=NR_reg_get2_uint2(prefix, "port", &port))) {
|
|
if (r != R_NOT_FOUND)
|
|
ABORT(r);
|
|
port = 0;
|
|
}
|
|
|
|
if ((r=NR_reg_alloc2_string(prefix, "protocol", &protocol))) {
|
|
if (r != R_NOT_FOUND)
|
|
ABORT(r);
|
|
+ p = IPPROTO_UDP;
|
|
+
|
|
protocol = 0;
|
|
}
|
|
else {
|
|
if (!strcasecmp("tcp", protocol))
|
|
p = IPPROTO_TCP;
|
|
else if (!strcasecmp("udp", protocol))
|
|
p = IPPROTO_UDP;
|
|
else
|
|
ABORT(R_BAD_DATA);
|
|
}
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/addrs.c src/stun/addrs.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/addrs.c 2012-09-16 16:26:10.000000000 -0700
|
|
+++ src/stun/addrs.c 2012-10-06 09:42:43.000000000 -0700
|
|
@@ -46,20 +46,22 @@
|
|
#include <sys/sysctl.h>
|
|
#include <sys/param.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/syslog.h>
|
|
#include <net/if.h>
|
|
#ifndef LINUX
|
|
#include <net/if_var.h>
|
|
#include <net/if_dl.h>
|
|
#include <net/if_types.h>
|
|
#include <sys/sockio.h>
|
|
+#else
|
|
+#include <linux/if.h>
|
|
#endif
|
|
#include <net/route.h>
|
|
|
|
/* IP */
|
|
#include <netinet/in.h>
|
|
#ifdef LINUX
|
|
#include "sys/ioctl.h"
|
|
#else
|
|
#include <netinet/in_var.h>
|
|
#endif
|
|
@@ -105,20 +107,23 @@
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <err.h>
|
|
|
|
static void stun_rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
|
|
static int stun_grab_addrs(char *name, int addrcount,
|
|
struct ifa_msghdr *ifam,
|
|
nr_transport_addr addrs[], int maxaddrs, int *count);
|
|
+static int
|
|
+nr_stun_is_duplicate_addr(nr_transport_addr addrs[], int count, nr_transport_addr *addr);
|
|
+
|
|
|
|
/*
|
|
* Expand the compacted form of addresses as returned via the
|
|
* configuration read via sysctl().
|
|
*/
|
|
#define ROUNDUP(a) \
|
|
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
|
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
|
|
|
|
static void
|
|
@@ -135,21 +140,21 @@
|
|
continue;
|
|
rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
|
|
ADVANCE(cp, sa);
|
|
}
|
|
}
|
|
|
|
static int
|
|
stun_grab_addrs(char *name, int addrcount, struct ifa_msghdr *ifam, nr_transport_addr addrs[], int maxaddrs, int *count)
|
|
{
|
|
int r,_status;
|
|
- NR_SOCKET s = -1;
|
|
+ int s = -1;
|
|
struct ifreq ifr;
|
|
struct rt_addrinfo info;
|
|
struct sockaddr_in *sin;
|
|
|
|
ifr.ifr_addr.sa_family = AF_INET;
|
|
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
|
|
|
|
if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) {
|
|
r_log(NR_LOG_STUN, LOG_WARNING, "unable to obtain addresses from socket");
|
|
ABORT(R_FAILED);
|
|
@@ -180,21 +185,20 @@
|
|
addrcount--;
|
|
|
|
if (*count >= maxaddrs) {
|
|
r_log(NR_LOG_STUN, LOG_WARNING, "Address list truncated at %d out of entries", maxaddrs, maxaddrs+addrcount);
|
|
break;
|
|
}
|
|
|
|
ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
|
|
}
|
|
|
|
-
|
|
_status = 0;
|
|
abort:
|
|
if (s != -1) close(s);
|
|
return _status;
|
|
}
|
|
|
|
static int
|
|
stun_get_mib_addrs(nr_transport_addr addrs[], int maxaddrs, int *count)
|
|
{
|
|
int _status;
|
|
@@ -551,44 +555,48 @@
|
|
#else
|
|
|
|
static int
|
|
stun_get_siocgifconf_addrs(nr_transport_addr addrs[], int maxaddrs, int *count)
|
|
{
|
|
struct ifconf ifc;
|
|
int _status;
|
|
int s = socket( AF_INET, SOCK_DGRAM, 0 );
|
|
int len = 100 * sizeof(struct ifreq);
|
|
int r;
|
|
+ int e;
|
|
+ char *ptr;
|
|
+ int tl;
|
|
+ int n;
|
|
+ struct ifreq ifr2;
|
|
|
|
char buf[ len ];
|
|
|
|
ifc.ifc_len = len;
|
|
ifc.ifc_buf = buf;
|
|
|
|
- int e = ioctl(s,SIOCGIFCONF,&ifc);
|
|
- char *ptr = buf;
|
|
- int tl = ifc.ifc_len;
|
|
- int n=0;
|
|
+ e = ioctl(s,SIOCGIFCONF,&ifc);
|
|
+ ptr = buf;
|
|
+ tl = ifc.ifc_len;
|
|
+ n=0;
|
|
|
|
while ( (tl > 0) && ( n < maxaddrs) )
|
|
{
|
|
struct ifreq* ifr = (struct ifreq *)ptr;
|
|
|
|
#ifdef LINUX
|
|
- int si = sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr);
|
|
+ int si = sizeof(struct ifreq);
|
|
#else
|
|
int si = sizeof(ifr->ifr_name) + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr));
|
|
#endif
|
|
tl -= si;
|
|
ptr += si;
|
|
|
|
- struct ifreq ifr2;
|
|
ifr2 = *ifr;
|
|
|
|
e = ioctl(s,SIOCGIFADDR,&ifr2);
|
|
if ( e == -1 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//r_log(NR_LOG_STUN, LOG_ERR, "ioctl addr e = %d",e);
|
|
|
|
@@ -603,21 +611,21 @@
|
|
|
|
close(s);
|
|
|
|
*count = n;
|
|
|
|
_status = 0;
|
|
return _status;
|
|
}
|
|
#endif
|
|
|
|
-int
|
|
+static int
|
|
nr_stun_is_duplicate_addr(nr_transport_addr addrs[], int count, nr_transport_addr *addr)
|
|
{
|
|
int i;
|
|
int different;
|
|
|
|
for (i = 0; i < count; ++i) {
|
|
different = nr_transport_addr_cmp(&addrs[i], addr, NR_TRANSPORT_ADDR_CMP_MODE_ALL);
|
|
if (!different)
|
|
return 1; /* duplicate */
|
|
}
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/nr_socket_turn.c src/stun/nr_socket_turn.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/nr_socket_turn.c 2012-09-16 16:26:10.000000000 -0700
|
|
+++ src/stun/nr_socket_turn.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -246,17 +246,19 @@
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
|
|
return R_FAILED;
|
|
}
|
|
|
|
static int nr_socket_turn_close(void *obj)
|
|
{
|
|
+#ifndef NDEBUG
|
|
nr_socket_turn *sturn=obj;
|
|
assert(sturn->magic_cookie == nr_socket_turn_magic_cookie);
|
|
+#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* USE_TURN */
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_client_ctx.c src/stun/stun_client_ctx.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_client_ctx.c 2012-09-16 16:26:10.000000000 -0700
|
|
+++ src/stun/stun_client_ctx.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -38,21 +38,22 @@
|
|
#include <string.h>
|
|
|
|
#include <nr_api.h>
|
|
#include "stun.h"
|
|
#include "async_timer.h"
|
|
#include "registry.h"
|
|
#include "stun_reg.h"
|
|
#include "r_time.h"
|
|
|
|
static int nr_stun_client_send_request(nr_stun_client_ctx *ctx);
|
|
-static void nr_stun_client_timer_expired_cb(int a, int b, void *cb_arg);
|
|
+static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg);
|
|
+static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password);
|
|
|
|
int nr_stun_client_ctx_create(char *label, nr_socket *sock, nr_transport_addr *peer, UINT4 RTO, nr_stun_client_ctx **ctxp)
|
|
{
|
|
nr_stun_client_ctx *ctx=0;
|
|
int r,_status;
|
|
|
|
if ((r=nr_stun_startup()))
|
|
ABORT(r);
|
|
|
|
if(!(ctx=RCALLOC(sizeof(nr_stun_client_ctx))))
|
|
@@ -185,21 +186,21 @@
|
|
ctx->finished_cb = 0;
|
|
ctx->cb_arg = 0;
|
|
ctx->request_ct = 0;
|
|
ctx->timeout_ms = 0;
|
|
|
|
ctx->state = NR_STUN_CLIENT_STATE_INITTED;
|
|
|
|
return 0;
|
|
}
|
|
|
|
-static void nr_stun_client_timer_expired_cb(int a, int b, void *cb_arg)
|
|
+static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg)
|
|
{
|
|
int _status;
|
|
nr_stun_client_ctx *ctx=cb_arg;
|
|
struct timeval now;
|
|
INT8 ms_waited;
|
|
|
|
/* Prevent this timer from being cancelled later */
|
|
ctx->timer_handle=0;
|
|
|
|
/* Shouldn't happen */
|
|
@@ -387,21 +388,21 @@
|
|
}
|
|
|
|
_status=0;
|
|
abort:
|
|
if (_status) {
|
|
ctx->state=NR_STUN_CLIENT_STATE_FAILED;
|
|
}
|
|
return(_status);
|
|
}
|
|
|
|
-int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password)
|
|
+static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password)
|
|
{
|
|
*password = (Data*)arg;
|
|
if (!arg)
|
|
return(R_NOT_FOUND);
|
|
return(0);
|
|
}
|
|
|
|
int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *peer_addr)
|
|
{
|
|
int r,_status;
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_codec.c src/stun/stun_codec.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_codec.c 2012-09-16 16:26:10.000000000 -0700
|
|
+++ src/stun/stun_codec.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -73,20 +73,22 @@
|
|
static int nr_stun_decode_htonll(UCHAR *buf, int buflen, int *offset, UINT8 *data);
|
|
static int nr_stun_decode(int length, UCHAR *buf, int buflen, int *offset, UCHAR *data);
|
|
|
|
static int nr_stun_attr_string_illegal(nr_stun_attr_info *attr_info, int len, void *data, int max_bytes, int max_chars);
|
|
|
|
static int nr_stun_attr_error_code_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
|
|
static int nr_stun_attr_nonce_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
|
|
static int nr_stun_attr_realm_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
|
|
static int nr_stun_attr_server_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
|
|
static int nr_stun_attr_username_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
|
|
+static int
|
|
+nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data);
|
|
|
|
|
|
int
|
|
nr_stun_encode_htons(UINT2 data, int buflen, UCHAR *buf, int *offset)
|
|
{
|
|
UINT2 d = htons(data);
|
|
|
|
if (*offset + sizeof(d) >= buflen) {
|
|
r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %d >= %d", *offset, sizeof(d), buflen);
|
|
return R_BAD_DATA;
|
|
@@ -632,21 +634,21 @@
|
|
}
|
|
|
|
fingerprint->checksum = checksum ^ 0x5354554e;
|
|
|
|
r_log(NR_LOG_STUN, LOG_DEBUG, "Computed FINGERPRINT %08x", fingerprint->checksum);
|
|
|
|
fingerprint->valid = 1;
|
|
return nr_stun_attr_codec_UINT4.encode(attr_info, &fingerprint->checksum, offset, buflen, buf, attrlen);
|
|
}
|
|
|
|
-int
|
|
+static int
|
|
nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
|
|
{
|
|
int r,_status;
|
|
nr_stun_attr_fingerprint *fingerprint = data;
|
|
nr_stun_message_header *header = (nr_stun_message_header*)buf;
|
|
int length;
|
|
UINT4 checksum;
|
|
|
|
if ((r=nr_stun_attr_codec_UINT4.decode(attr_info, attrlen, buf, offset, buflen, &fingerprint->checksum)))
|
|
ABORT(r);
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_proc.c src/stun/stun_proc.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_proc.c 2012-09-16 16:26:10.000000000 -0700
|
|
+++ src/stun/stun_proc.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -43,20 +43,22 @@
|
|
#include <time.h>
|
|
#else /* UNIX */
|
|
#include <string.h>
|
|
#endif /* end UNIX */
|
|
#include <assert.h>
|
|
|
|
#include "stun.h"
|
|
#include "stun_reg.h"
|
|
#include "registry.h"
|
|
|
|
+static int
|
|
+nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res);
|
|
|
|
/* draft-ietf-behave-rfc3489bis-10.txt S 7.3 */
|
|
int
|
|
nr_stun_receive_message(nr_stun_message *req, nr_stun_message *msg)
|
|
{
|
|
int _status;
|
|
nr_stun_message_attribute *attr;
|
|
|
|
#ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
|
|
/* if this message was generated by an RFC 3489 impementation,
|
|
@@ -371,21 +373,21 @@
|
|
/* nothing to check in this case */
|
|
break;
|
|
#endif /* USE_STUND_0_96 */
|
|
}
|
|
|
|
_status=0;
|
|
abort:
|
|
return _status;
|
|
}
|
|
|
|
-int
|
|
+static int
|
|
nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res)
|
|
{
|
|
int r,_status;
|
|
char *realm = 0;
|
|
char *nonce;
|
|
UINT2 size;
|
|
|
|
if ((r=NR_reg_alloc_string(NR_STUN_REG_PREF_SERVER_REALM, &realm)))
|
|
ABORT(r);
|
|
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_server_ctx.c src/stun/stun_server_ctx.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_server_ctx.c 2012-09-16 16:26:10.000000000 -0700
|
|
+++ src/stun/stun_server_ctx.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -114,21 +114,21 @@
|
|
STAILQ_INSERT_TAIL(&ctx->clients,clnt,entry);
|
|
|
|
_status=0;
|
|
abort:
|
|
if(_status){
|
|
nr_stun_server_destroy_client(clnt);
|
|
}
|
|
return(_status);
|
|
}
|
|
|
|
-int nr_stun_server_get_password(void *arg, nr_stun_message *msg, Data **password)
|
|
+static int nr_stun_server_get_password(void *arg, nr_stun_message *msg, Data **password)
|
|
{
|
|
int _status;
|
|
nr_stun_server_ctx *ctx = (nr_stun_server_ctx*)arg;
|
|
nr_stun_server_client *clnt = 0;
|
|
nr_stun_message_attribute *username_attribute;
|
|
|
|
if ((nr_stun_get_message_client(ctx, msg, &clnt))) {
|
|
if (! nr_stun_message_has_attribute(msg, NR_STUN_ATTR_USERNAME, &username_attribute)) {
|
|
r_log(NR_LOG_STUN,LOG_NOTICE,"STUN-SERVER(%s): Missing Username",ctx->label);
|
|
ABORT(R_NOT_FOUND);
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_util.c src/stun/stun_util.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_util.c 2012-09-16 16:26:10.000000000 -0700
|
|
+++ src/stun/stun_util.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -94,21 +94,20 @@
|
|
_status = 0;
|
|
abort:
|
|
return _status;
|
|
}
|
|
|
|
int
|
|
nr_stun_find_local_addresses(nr_transport_addr addrs[], int maxaddrs, int *count)
|
|
{
|
|
int r,_status;
|
|
NR_registry *children = 0;
|
|
- int i;
|
|
|
|
if ((r=NR_reg_get_child_count(NR_STUN_REG_PREF_ADDRESS_PRFX, (unsigned int*)count)))
|
|
if (r == R_NOT_FOUND)
|
|
*count = 0;
|
|
else
|
|
ABORT(r);
|
|
|
|
if (*count == 0) {
|
|
if ((r=nr_stun_get_addrs(addrs, maxaddrs, 1, count)))
|
|
ABORT(r);
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/turn_client_ctx.c src/stun/turn_client_ctx.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/turn_client_ctx.c 2012-09-16 16:26:10.000000000 -0700
|
|
+++ src/stun/turn_client_ctx.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -55,21 +55,24 @@
|
|
};
|
|
|
|
static int TURN_PHASE_MODE[NUMBER_OF_STUN_CTX] = {
|
|
NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST1,
|
|
NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST2,
|
|
NR_TURN_CLIENT_MODE_SET_ACTIVE_DEST_REQUEST
|
|
};
|
|
|
|
|
|
static int nr_turn_client_next_action(nr_turn_client_ctx *ctx, int stun_ctx_state);
|
|
-static void nr_turn_client_cb(int s, int how, void *cb_arg);
|
|
+static void nr_turn_client_cb(NR_SOCKET s, int how, void *cb_arg);
|
|
+static int
|
|
+nr_turn_client_prepare_start(nr_turn_client_ctx *ctx, char *username, Data *password, UINT4 bandwidth_kbps, UINT4 lifetime_secs, NR_async_cb finished_cb, void *cb_arg);
|
|
+
|
|
|
|
int
|
|
nr_turn_client_next_action(nr_turn_client_ctx *ctx, int stun_ctx_state)
|
|
{
|
|
int r,_status;
|
|
|
|
assert(ctx->phase >= -1 && ctx->phase < NUMBER_OF_STUN_CTX);
|
|
|
|
switch (ctx->state) {
|
|
//case NR_TURN_CLIENT_STATE_ALLOCATING:
|
|
@@ -147,21 +150,21 @@
|
|
* because as a side effect this ctx may be operated on in the
|
|
* callback */
|
|
finished_cb(0,0,ctx->cb_arg);
|
|
}
|
|
}
|
|
|
|
return(_status);
|
|
}
|
|
|
|
void
|
|
-nr_turn_client_cb(int s, int how, void *cb_arg)
|
|
+nr_turn_client_cb(NR_SOCKET s, int how, void *cb_arg)
|
|
{
|
|
int r,_status;
|
|
nr_turn_client_ctx *ctx = (nr_turn_client_ctx*)cb_arg;
|
|
nr_stun_client_ctx *stun_ctx = ctx->stun_ctx[ctx->phase];
|
|
|
|
assert(ctx->phase >= 0);
|
|
|
|
if ((r=nr_turn_client_next_action(ctx, stun_ctx->state)))
|
|
ABORT(r);
|
|
|
|
@@ -234,21 +237,21 @@
|
|
|
|
RFREE(ctx->username);
|
|
r_data_destroy(&ctx->password);
|
|
|
|
RFREE(ctx->label);
|
|
RFREE(ctx);
|
|
|
|
return(0);
|
|
}
|
|
|
|
-int
|
|
+static int
|
|
nr_turn_client_prepare_start(nr_turn_client_ctx *ctx, char *username, Data *password, UINT4 bandwidth_kbps, UINT4 lifetime_secs, NR_async_cb finished_cb, void *cb_arg)
|
|
{
|
|
int r,_status;
|
|
nr_stun_client_allocate_request1_params *allocate_request1 = 0;
|
|
nr_stun_client_allocate_request2_params *allocate_request2 = 0;
|
|
nr_stun_client_allocate_response1_results *allocate_response1 = 0;
|
|
// nr_stun_client_allocate_response2_results *allocate_response2;
|
|
|
|
if (ctx->state != NR_TURN_CLIENT_STATE_INITTED)
|
|
ABORT(R_NOT_PERMITTED);
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/util/ice_util.c src/util/ice_util.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/util/ice_util.c 2012-09-16 16:26:10.000000000 -0700
|
|
+++ src/util/ice_util.c 2012-10-06 08:30:22.000000000 -0700
|
|
@@ -31,20 +31,21 @@
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
static char *RCSSTRING __UNUSED__="$Id: ice_util.c,v 1.2 2008/04/28 17:59:05 ekr Exp $";
|
|
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include "nr_api.h"
|
|
+#include "ice_util.h"
|
|
|
|
int nr_concat_strings(char **outp,...)
|
|
{
|
|
va_list ap;
|
|
char *s,*out=0;
|
|
int len=0;
|
|
int _status;
|
|
|
|
va_start(ap,outp);
|
|
while(s=va_arg(ap,char *)){
|
|
diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/util/mbslen.c src/util/mbslen.c
|
|
--- /Users/ekr/dev/mtransport-import-references/nICEr/src/util/mbslen.c 2012-09-16 16:26:10.000000000 -0700
|
|
+++ src/util/mbslen.c 2012-10-06 08:31:01.000000000 -0700
|
|
@@ -56,21 +56,21 @@
|
|
{
|
|
#ifdef DARWIN
|
|
static locale_t loc = 0;
|
|
static int initialized = 0;
|
|
#endif /* DARWIN */
|
|
#ifdef WIN32
|
|
char *my_locale=0;
|
|
unsigned int i;
|
|
#endif /* WIN32 */
|
|
int _status;
|
|
- int nbytes;
|
|
+ size_t nbytes;
|
|
int nchars;
|
|
mbstate_t mbs;
|
|
|
|
#ifdef DARWIN
|
|
if (! initialized) {
|
|
initialized = 1;
|
|
loc = newlocale(LC_CTYPE_MASK, "UTF-8", LC_GLOBAL_LOCALE);
|
|
}
|
|
|
|
if (loc == 0) {
|
|
@@ -102,25 +102,28 @@
|
|
|
|
memset(&mbs, 0, sizeof(mbs));
|
|
nchars = 0;
|
|
|
|
#ifdef DARWIN
|
|
while (*s != '\0' && (nbytes = mbrlen_l(s, strlen(s), &mbs, loc)) != 0)
|
|
#else
|
|
while (*s != '\0' && (nbytes = mbrlen(s, strlen(s), &mbs)) != 0)
|
|
#endif /* DARWIN */
|
|
{
|
|
- assert(nbytes >= 0);
|
|
- if (nbytes == (size_t)-1) /* should never happen */
|
|
+ if (nbytes == (size_t)-1) /* should never happen */ {
|
|
+ assert(0);
|
|
ABORT(R_INTERNAL);
|
|
- if (nbytes == (size_t)-2) /* encoding error */
|
|
+ }
|
|
+ if (nbytes == (size_t)-2) /* encoding error */ {
|
|
+ assert(0);
|
|
ABORT(R_BAD_DATA);
|
|
+ }
|
|
|
|
s += nbytes;
|
|
++nchars;
|
|
}
|
|
|
|
*ncharsp = nchars;
|
|
|
|
_status = 0;
|
|
abort:
|
|
#ifdef WIN32
|