Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BC
public
mediastreamer2
Commits
dcadb7e8
Commit
dcadb7e8
authored
Oct 11, 2012
by
Ghislain MARY
Browse files
Calculate average round trip time during ICE gathering.
parent
ee063141
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
100 additions
and
39 deletions
+100
-39
include/mediastreamer2/ice.h
include/mediastreamer2/ice.h
+17
-3
src/ice.c
src/ice.c
+83
-36
No files found.
include/mediastreamer2/ice.h
View file @
dcadb7e8
...
...
@@ -114,12 +114,18 @@ typedef struct _IceSession {
MSTimeSpec
gathering_end_ts
;
}
IceSession
;
typedef
struct
_IceStunServerCheckTransaction
{
UInt96
transactionID
;
MSTimeSpec
request_time
;
MSTimeSpec
response_time
;
}
IceStunServerCheckTransaction
;
typedef
struct
_IceStunServerCheck
{
ortp_socket_t
sock
;
int
srcport
;
UInt96
transaction
ID
;
MSTimeSpec
transmission_time
;
uint8_t
nb_transmissions
;
MSList
*
transaction
s
;
/**< List of IceStunServerCheckTransaction structures. */
MSTimeSpec
next_
transmission_time
;
bool_t
responded
;
}
IceStunServerCheck
;
/**
...
...
@@ -438,6 +444,14 @@ MS2_PUBLIC void ice_session_gather_candidates(IceSession *session, struct sockad
*/
MS2_PUBLIC
int
ice_session_gathering_duration
(
IceSession
*
session
);
/**
* Tell the average round trip time during the gathering process for an ICE session in ms.
*
* @param session A pointer to a session
* @return -1 if gathering has not been run, the average round trip time in ms otherwise.
*/
MS2_PUBLIC
int
ice_session_average_gathering_round_trip_time
(
IceSession
*
session
);
/**
* Select ICE candidates that will be used and notified in the SDP.
*
...
...
src/ice.c
View file @
dcadb7e8
...
...
@@ -111,13 +111,18 @@ typedef struct _LosingRemoteCandidate_InProgress_Failed {
bool_t
failed_candidates
;
}
LosingRemoteCandidate_InProgress_Failed
;
typedef
struct
_StunRequestRoundTripTime
{
int
nb_responses
;
int
sum
;
}
StunRequestRoundTripTime
;
static
MSTimeSpec
ice_current_time
(
void
);
static
MSTimeSpec
ice_add_ms
(
MSTimeSpec
orig
,
uint32_t
ms
);
static
int32_t
ice_compare_time
(
MSTimeSpec
ts1
,
MSTimeSpec
ts2
);
static
char
*
ice_inet_ntoa
(
struct
sockaddr
*
addr
,
int
addrlen
,
char
*
dest
,
int
destlen
);
static
void
transactionID2string
(
const
UInt96
*
tr_id
,
char
*
tr_id_str
);
static
void
ice_send_stun_server_binding_request
(
ortp_socket_t
sock
,
const
struct
sockaddr
*
server
,
socklen_t
addrlen
,
int
srcport
,
UInt96
*
transactionID
,
uint8_t
nb_transmissions
,
int
id
);
static
void
ice_send_stun_server_binding_request
(
ortp_socket_t
sock
,
const
struct
sockaddr
*
server
,
socklen_t
addrlen
,
IceStunServerCheck
*
check
);
static
int
ice_compare_transport_addresses
(
const
IceTransportAddress
*
ta1
,
const
IceTransportAddress
*
ta2
);
static
int
ice_compare_pair_priorities
(
const
IceCandidatePair
*
p1
,
const
IceCandidatePair
*
p2
);
static
int
ice_compare_pairs
(
const
IceCandidatePair
*
p1
,
const
IceCandidatePair
*
p2
);
...
...
@@ -315,8 +320,14 @@ static IceCandidatePair *ice_pair_new(IceCheckList *cl, IceCandidate* local_cand
return
pair
;
}
static
void
ice_free_stun_server_check_transaction
(
IceStunServerCheckTransaction
*
transaction
)
{
ms_free
(
transaction
);
}
static
void
ice_free_stun_server_check
(
IceStunServerCheck
*
check
)
{
ms_list_for_each
(
check
->
transactions
,
(
void
(
*
)(
void
*
))
ice_free_stun_server_check_transaction
);
ms_free
(
check
);
}
...
...
@@ -829,12 +840,10 @@ static void ice_check_list_gather_candidates(IceCheckList *cl, Session_Index *si
check
->
sock
=
sock
;
check
->
srcport
=
rtp_session_get_local_port
(
cl
->
rtp_session
);
if
(
si
->
index
==
0
)
{
check
->
transmission_time
=
ice_add_ms
(
curtime
,
ICE_DEFAULT_RTO_DURATION
);
check
->
nb_transmissions
=
1
;
ice_send_stun_server_binding_request
(
sock
,
(
struct
sockaddr
*
)
&
cl
->
session
->
ss
,
cl
->
session
->
ss_len
,
check
->
srcport
,
&
check
->
transactionID
,
check
->
nb_transmissions
,
check
->
sock
);
check
->
next_transmission_time
=
ice_add_ms
(
curtime
,
ICE_DEFAULT_RTO_DURATION
);
ice_send_stun_server_binding_request
(
sock
,
(
struct
sockaddr
*
)
&
cl
->
session
->
ss
,
cl
->
session
->
ss_len
,
check
);
}
else
{
check
->
transmission_time
=
ice_add_ms
(
curtime
,
2
*
si
->
index
*
ICE_DEFAULT_TA_DURATION
);
check
->
next_
transmission_time
=
ice_add_ms
(
curtime
,
2
*
si
->
index
*
ICE_DEFAULT_TA_DURATION
);
}
cl
->
stun_server_checks
=
ms_list_append
(
cl
->
stun_server_checks
,
check
);
}
...
...
@@ -843,7 +852,7 @@ static void ice_check_list_gather_candidates(IceCheckList *cl, Session_Index *si
check
=
(
IceStunServerCheck
*
)
ms_new0
(
IceStunServerCheck
,
1
);
check
->
sock
=
sock
;
check
->
srcport
=
rtp_session_get_local_port
(
cl
->
rtp_session
)
+
1
;
check
->
transmission_time
=
ice_add_ms
(
curtime
,
2
*
si
->
index
*
ICE_DEFAULT_TA_DURATION
+
ICE_DEFAULT_TA_DURATION
);
check
->
next_
transmission_time
=
ice_add_ms
(
curtime
,
2
*
si
->
index
*
ICE_DEFAULT_TA_DURATION
+
ICE_DEFAULT_TA_DURATION
);
cl
->
stun_server_checks
=
ms_list_append
(
cl
->
stun_server_checks
,
check
);
}
si
->
index
++
;
...
...
@@ -879,6 +888,35 @@ int ice_session_gathering_duration(IceSession *session)
+
((
session
->
gathering_end_ts
.
tv_nsec
-
session
->
gathering_start_ts
.
tv_nsec
)
/
1000000
.
0
);
}
static
void
ice_transaction_sum_gathering_round_trip_time
(
const
IceStunServerCheckTransaction
*
transaction
,
StunRequestRoundTripTime
*
rtt
)
{
if
((
transaction
->
response_time
.
tv_sec
!=
0
)
&&
(
transaction
->
response_time
.
tv_nsec
!=
0
))
{
rtt
->
nb_responses
++
;
rtt
->
sum
+=
ice_compare_time
(
transaction
->
response_time
,
transaction
->
request_time
);
}
}
static
void
ice_stun_server_check_sum_gathering_round_trip_time
(
const
IceStunServerCheck
*
check
,
StunRequestRoundTripTime
*
rtt
)
{
ms_list_for_each2
(
check
->
transactions
,
(
void
(
*
)(
void
*
,
void
*
))
ice_transaction_sum_gathering_round_trip_time
,
rtt
);
}
static
void
ice_check_list_sum_gathering_round_trip_times
(
const
IceCheckList
*
cl
,
StunRequestRoundTripTime
*
rtt
)
{
ms_list_for_each2
(
cl
->
stun_server_checks
,
(
void
(
*
)(
void
*
,
void
*
))
ice_stun_server_check_sum_gathering_round_trip_time
,
rtt
);
}
int
ice_session_average_gathering_round_trip_time
(
IceSession
*
session
)
{
StunRequestRoundTripTime
rtt
;
if
((
session
->
gathering_start_ts
.
tv_sec
==
-
1
)
||
(
session
->
gathering_end_ts
.
tv_sec
==
-
1
))
return
-
1
;
memset
(
&
rtt
,
0
,
sizeof
(
rtt
));
ms_list_for_each2
(
session
->
streams
,
(
void
(
*
)(
void
*
,
void
*
))
ice_check_list_sum_gathering_round_trip_times
,
&
rtt
);
if
(
rtt
.
nb_responses
==
0
)
return
-
1
;
return
(
rtt
.
sum
/
rtt
.
nb_responses
);
}
/******************************************************************************
* CANDIDATES SELECTION *
...
...
@@ -942,7 +980,7 @@ static IceTransaction * ice_find_transaction(const IceCheckList *cl, const IceCa
* STUN PACKETS HANDLING *
*****************************************************************************/
static
void
ice_send_stun_server_binding_request
(
ortp_socket_t
sock
,
const
struct
sockaddr
*
server
,
socklen_t
addrlen
,
int
srcport
,
UInt96
*
transactionID
,
uint8_t
nb_transmissions
,
int
id
)
static
void
ice_send_stun_server_binding_request
(
ortp_socket_t
sock
,
const
struct
sockaddr
*
server
,
socklen_t
addrlen
,
IceStunServerCheck
*
check
)
{
StunMessage
msg
;
StunAtrString
username
;
...
...
@@ -955,21 +993,16 @@ static void ice_send_stun_server_binding_request(ortp_socket_t sock, const struc
memset
(
&
msg
,
0
,
sizeof
(
StunMessage
));
memset
(
&
username
,
0
,
sizeof
(
username
));
memset
(
&
password
,
0
,
sizeof
(
password
));
stunBuildReqSimple
(
&
msg
,
&
username
,
FALSE
,
FALSE
,
id
);
if
(
nb_transmissions
>
1
)
{
/* Keep the same transaction ID for retransmissions. */
memcpy
(
&
msg
.
msgHdr
.
tr_id
,
transactionID
,
sizeof
(
msg
.
msgHdr
.
tr_id
));
}
stunBuildReqSimple
(
&
msg
,
&
username
,
FALSE
,
FALSE
,
check
->
sock
);
len
=
stunEncodeMessage
(
&
msg
,
buf
,
len
,
&
password
);
if
(
len
>
0
)
{
IceStunServerCheckTransaction
*
transaction
=
ms_new0
(
IceStunServerCheckTransaction
,
1
);
transaction
->
request_time
=
ice_current_time
();
memcpy
(
&
transaction
->
transactionID
,
&
msg
.
msgHdr
.
tr_id
,
sizeof
(
transaction
->
transactionID
));
check
->
transactions
=
ms_list_append
(
check
->
transactions
,
transaction
);
transactionID2string
(
&
msg
.
msgHdr
.
tr_id
,
tr_id_str
);
if
(
nb_transmissions
>
1
)
{
ms_message
(
"ice: Retransmit STUN binding request from port %u [%s]"
,
srcport
,
tr_id_str
);
}
else
{
ms_message
(
"ice: Send STUN binding request from port %u [%s]"
,
srcport
,
tr_id_str
);
}
ms_message
(
"ice: Send STUN binding request from port %u [%s]"
,
check
->
srcport
,
tr_id_str
);
sendMessage
(
sock
,
buf
,
len
,
htonl
(
servaddr
->
sin_addr
.
s_addr
),
htons
(
servaddr
->
sin_port
));
memcpy
(
transactionID
,
&
msg
.
msgHdr
.
tr_id
,
sizeof
(
*
transactionID
));
}
}
...
...
@@ -1726,6 +1759,16 @@ static int ice_find_not_failed_or_succeeded_pair(const IceCandidatePair *pair, c
return
!
((
pair
->
state
!=
ICP_Failed
)
&&
(
pair
->
state
!=
ICP_Succeeded
));
}
static
int
ice_compare_transactionIDs
(
const
UInt96
*
tr_id1
,
const
UInt96
*
tr_id2
)
{
return
memcmp
(
tr_id1
,
tr_id2
,
sizeof
(
UInt96
));
}
static
int
ice_find_non_responded_stun_server_check
(
const
IceStunServerCheck
*
check
,
const
void
*
dummy
)
{
return
(
check
->
responded
==
TRUE
);
}
static
void
ice_handle_received_binding_response
(
IceCheckList
*
cl
,
RtpSession
*
rtp_session
,
const
OrtpEventData
*
evt_data
,
const
StunMessage
*
msg
,
const
StunAddress4
*
remote_addr
)
{
IceCandidatePair
*
succeeded_pair
;
...
...
@@ -1747,20 +1790,26 @@ static void ice_handle_received_binding_response(IceCheckList *cl, RtpSession *r
sock
=
ice_get_socket_from_rtp_session
(
rtp_session
,
evt_data
);
elem
=
ms_list_find_custom
(
cl
->
stun_server_checks
,
(
MSCompareFunc
)
ice_find_stun_server_check
,
&
sock
);
if
(
elem
!=
NULL
)
{
componentID
=
ice_get_componentID_from_rtp_session
(
evt_data
);
if
((
componentID
>
0
)
&&
(
ice_parse_stun_server_binding_response
(
msg
,
addr
,
sizeof
(
addr
),
&
port
)
>=
0
))
{
base_elem
=
ms_list_find_custom
(
cl
->
local_candidates
,
(
MSCompareFunc
)
ice_find_host_candidate
,
&
componentID
);
if
(
base_elem
!=
NULL
)
{
candidate
=
(
IceCandidate
*
)
base_elem
->
data
;
ice_add_local_candidate
(
cl
,
"srflx"
,
addr
,
port
,
componentID
,
candidate
);
ms_message
(
"ice: Add candidate obtained by STUN: %s:%u:srflx"
,
addr
,
port
);
IceStunServerCheckTransaction
*
transaction
;
IceStunServerCheck
*
check
=
(
IceStunServerCheck
*
)
elem
->
data
;
elem
=
ms_list_find_custom
(
check
->
transactions
,
(
MSCompareFunc
)
ice_compare_transactionIDs
,
&
msg
->
msgHdr
.
tr_id
);
transaction
=
(
IceStunServerCheckTransaction
*
)
elem
->
data
;
if
(
transaction
!=
NULL
)
{
componentID
=
ice_get_componentID_from_rtp_session
(
evt_data
);
if
((
componentID
>
0
)
&&
(
ice_parse_stun_server_binding_response
(
msg
,
addr
,
sizeof
(
addr
),
&
port
)
>=
0
))
{
base_elem
=
ms_list_find_custom
(
cl
->
local_candidates
,
(
MSCompareFunc
)
ice_find_host_candidate
,
&
componentID
);
if
(
base_elem
!=
NULL
)
{
candidate
=
(
IceCandidate
*
)
base_elem
->
data
;
ice_add_local_candidate
(
cl
,
"srflx"
,
addr
,
port
,
componentID
,
candidate
);
ms_message
(
"ice: Add candidate obtained by STUN: %s:%u:srflx"
,
addr
,
port
);
}
transaction
->
response_time
=
evt_data
->
ts
;
check
->
responded
=
TRUE
;
}
stun_server_response
=
TRUE
;
}
ms_free
(
elem
->
data
);
cl
->
stun_server_checks
=
ms_list_remove_link
(
cl
->
stun_server_checks
,
elem
);
stun_server_response
=
TRUE
;
}
if
(
ms_list_
size
(
cl
->
stun_server_checks
)
==
0
)
{
if
(
ms_list_
find_custom
(
cl
->
stun_server_checks
,
(
MSCompareFunc
)
ice_find_non_responded_stun_server_check
,
NULL
)
==
NULL
)
{
cl
->
gathering_candidates
=
FALSE
;
cl
->
gathering_finished
=
TRUE
;
ms_message
(
"ice: Finished candidates gathering for check list %p"
,
cl
);
...
...
@@ -2832,12 +2881,10 @@ static void ice_send_stun_server_checks(IceStunServerCheck *check, IceCheckList
{
MSTimeSpec
curtime
=
ice_current_time
();
if
(
ice_compare_time
(
curtime
,
check
->
transmission_time
)
>=
0
)
{
check
->
nb_transmissions
++
;
if
(
check
->
nb_transmissions
<=
ICE_MAX_STUN_REQUEST_RETRANSMISSIONS
)
{
check
->
transmission_time
=
ice_add_ms
(
curtime
,
ICE_DEFAULT_RTO_DURATION
);
ice_send_stun_server_binding_request
(
check
->
sock
,
(
struct
sockaddr
*
)
&
cl
->
session
->
ss
,
cl
->
session
->
ss_len
,
check
->
srcport
,
&
check
->
transactionID
,
check
->
nb_transmissions
,
check
->
sock
);
if
(
ice_compare_time
(
curtime
,
check
->
next_transmission_time
)
>=
0
)
{
if
(
ms_list_size
(
check
->
transactions
)
<
ICE_MAX_STUN_REQUEST_RETRANSMISSIONS
)
{
check
->
next_transmission_time
=
ice_add_ms
(
curtime
,
ICE_DEFAULT_RTO_DURATION
);
ice_send_stun_server_binding_request
(
check
->
sock
,
(
struct
sockaddr
*
)
&
cl
->
session
->
ss
,
cl
->
session
->
ss_len
,
check
);
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment