mirror of https://github.com/sipwise/rtpengine.git
Squashed commit of the following:
commit 00213e66c74d402d2c3045eabeb5a10fa68f10c7
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Fri Feb 27 09:40:04 2015 -0500
perform ICE restart if we change ports
commit 27fbcbd6cbebdd071c1fa960c6e55f016534d171
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 15:58:12 2015 -0500
locking fixes
commit 60c1c5ae13b2c11720ee099daea1e3cdebea6317
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 15:58:06 2015 -0500
unkernelize when ICE completes
commit 1d816f9864ce31ea9a55a0bdf243a9900e597cdf
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 15:54:44 2015 -0500
relaxed locking where not needed
commit 75b58a9093d97daa5b2f4f8c1790f3b0f64117f8
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 11:46:08 2015 -0500
use atomic bitfield instead of bitfield+mutex
commit 03552eeed92aad419c1ad3cb9cfe5a7bded7f601
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 11:24:59 2015 -0500
shuffle around aux.h a bit more
commit b9b8a3aa5ef4d1a9026977465716fdbadf96917a
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 11:16:12 2015 -0500
remove some code redundancy through a "state machine"
commit 0b4bfef1b18b75e22611f18e510209c743708cd6
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 10:10:41 2015 -0500
reorder to match struct
commit a2a51d81a8f02dbb0fd8afe103ae0b0fa2a28dcf
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 10:10:03 2015 -0500
clear more states for ICE restart
commit d554a2b858dc3655d72d037a16c12e7eea243e1b
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 09:58:29 2015 -0500
dont duplicate candidates on re-invite
commit 4c804652b7985046d0214e4a90e67da9cce8fd03
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 09:58:20 2015 -0500
retain ICE role across re-invites
commit 4a586dd72d9f31ba87fb82e1e0e3602b467c252a
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 09:42:09 2015 -0500
eliminate duplicate log messages
commit ef0be2e308e1e3c3ce063afd2854e3fb749d813a
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 26 09:32:36 2015 -0500
fix incorrect log message
commit 2544b60f00b3b03fd64ac6e4b4e8ec20423b7745
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 15:26:48 2015 -0500
better logging for ICE agents
commit c42807384efa167afa08e10296b5177526efb9ba
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 15:18:27 2015 -0500
dont run ICE checks if we dont have a password
commit 1b56cb75b5912fd5aa6e3c66bf792e56f706d249
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 15:16:19 2015 -0500
ICE pairs should go in triggered queue only once
commit d10c56f3ae6172240c2a786fcacb14e5df177f13
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 14:04:00 2015 -0500
obsolete the ICE agent running flag
commit 52237e33995d8b6ff25e898daee7d46af37992ed
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 14:02:06 2015 -0500
cease checks once ICE is completed
commit 5332d18612d5c8e068590a6b4e708b969d385844
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 13:53:57 2015 -0500
fix ICE completion logging
commit 85f5fd63aa24998d206657cabeaf3fecbe4d187a
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 13:53:33 2015 -0500
make better use of bit flags
commit 796b48bb78601e98270c182e2ad60f1c5278091a
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 12:09:46 2015 -0500
improved learned candidate pairing and completion logic
commit d15561072e24a842e4fc7f074ec6ecadcf96cd8e
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 11:21:45 2015 -0500
support upper case transport strings
commit 557da7b1c39807bad119f23e57c4d31d77962103
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 10:43:57 2015 -0500
use struct endpoint in ice candidates
commit 951040bfd62eb52bccb091d99b7b8289ccef2cc9
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 10:31:13 2015 -0500
more meaningful ICE log messages
commit 8ec2426bd3101c4f381e95cd0686b6b1a6fec658
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 09:54:49 2015 -0500
shut down agent if no components - limit number of candidates
commit 149260f3a6eaa5f58a6f9071e0b05a18914b987d
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 25 09:44:13 2015 -0500
handle ICE restarts
commit 6a18c31f81ab94df1f5d5a701339b14be0e10ee5
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 16:29:01 2015 -0500
dont clear succeeded flag when nominating
commit 93e0861d0250f9190b16b14c3f4fe33a359d5d47
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 16:21:40 2015 -0500
use correct pwd in stun binding response
commit 32ba3ea406e30d168834f93d3e454d812820cf55
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 16:03:09 2015 -0500
use deterministic foundation for prflx cands
commit 2f2dc9151566d0bf2eebbaf02845718229be0e3d
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 15:21:13 2015 -0500
handle initial ICE role
commit a6b8ad25e6c326f2a0edda12db5dff910bc3d771
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 14:43:47 2015 -0500
another ICE scheduling fix
commit c572b04e55b695af28efed4fc4dc8c798989f02d
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 14:14:29 2015 -0500
make ICE aware of rtcp-mux
commit 93cd2d2560809f82e8ab9ffb2f5e2725fb439f4c
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 14:13:27 2015 -0500
print timestamp when logging to stderr
commit 22a52ffda2f21dba37c44c9e148a4cbe830be52e
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 14:13:13 2015 -0500
ICE scheduling fixes
commit 5d2d1a7739ef7d41514352fbf84deddcbd4500af
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 13:27:59 2015 -0500
increase ICE pwd length to make chrome happy
commit ceff6698db33fa7a4500cb94a4fa377a7629b8aa
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 13:09:54 2015 -0500
dont discard RTP if ICE hasnt finished yet
commit e809877d0ee0e7d60f3826be091c59145a2a9e19
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 13:06:31 2015 -0500
implement remote-candidates (untested)
commit 41670eadbbbe99a35a70158cf054b20a84c9c51b
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 11:58:13 2015 -0500
shut down ICE agent when everything fails
commit 1ca26c4a815c3f78b0c97cc6b5a5d794a64926f4
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 11:10:46 2015 -0500
fix up SDP output for ICE candidates
commit 0287d68f3330d9b2b7e61ea77ce9c77dec83d217
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 10:09:49 2015 -0500
process ICE completion and fire up DTLS if desired
commit 5b6386036b05f43ccbdbeb63ea49d8585498cfd0
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 09:37:52 2015 -0500
use a btree to schedule ice checks
commit 2bc25f1e0f5acee9262186a866fcc851d2e911ba
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 24 09:37:02 2015 -0500
convert shutdown condition into global var
commit ecf0c5587c62fcb39c8a67e510bcc7e6e3c10162
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Mon Feb 23 14:50:46 2015 -0500
replace poller_now with timeval g_now
commit 164ecdd7ac5d37641de32c98bba7db2e23446b91
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Mon Feb 23 13:00:15 2015 -0500
handle nominations if we're controlling
commit d013659365c33a3e802e1ec734dc45361531071d
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Mon Feb 23 12:11:40 2015 -0500
copy controlling/ed role into agent
commit 09f1cae14a2dd1aaf06b1c81ebe30ad198b96ec6
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Mon Feb 23 12:02:54 2015 -0500
separate nominated pairs from valid pairs
commit f75f338cded413617318288ceb6a664771e9434c
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Mon Feb 23 11:55:30 2015 -0500
organize aux.h into sections
commit d6acee1392a9cb34bd51524d11fc3d1e40f788cd
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Mon Feb 23 11:55:17 2015 -0500
use b-tree for various ICE lists
commit af9804d139cf50c6908ac760c9179685b3a872f0
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Fri Feb 20 16:21:09 2015 -0500
prepare to finalize ice processing
commit 18df118375cb30015f703cfbd9ed5c5020ff122e
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Fri Feb 20 16:19:50 2015 -0500
prettier logging
commit 280755c61a5e014422acfd45a30e98b2ec6b9efa
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Fri Feb 20 15:02:14 2015 -0500
implement unfreezing of other components on success
commit 5d13657d5b7a962ebbbd96677909ba49f59492dc
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Fri Feb 20 15:00:24 2015 -0500
bitfield access macros
commit 71746ad6a1171234adbb274ad67159a890c59c3c
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Fri Feb 20 14:15:05 2015 -0500
handle ice updates and duplicate candidates
commit 02309d1b5b39333778e04ef61b61be3ba81cb9d3
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Fri Feb 20 12:22:29 2015 -0500
handle role conflicts
commit 52acf54ba5b2fe694f647e828ab92b0bf82bdce1
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Fri Feb 20 10:24:01 2015 -0500
proper pair priorities calculation
commit 307af79e8d347d703b065c5c7b7b0321f1ca82fb
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Fri Feb 20 09:54:18 2015 -0500
fix address family mixups
commit 7cbfd4d36a21ad917974259bcb37c5cea340bf4e
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Fri Feb 20 09:14:49 2015 -0500
delay dtls startup and timeout checks while ice is running
commit 2a8ab752280ebf9961137414c88c6afbf03b0df2
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 19 16:47:56 2015 -0500
process ice/stun responses
commit 92da323dcff4f725e29ab378ede1aab68d9900a1
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 19 15:14:30 2015 -0500
adding stun server script for testing
commit c5cfeb122cc8503a8f4c901e279eac2932feb3f7
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 19 13:42:40 2015 -0500
act on stun requests, learn prflx candidates
commit 1cafd35e7a5105214aa4af5b03d14054f02c668e
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 19 13:30:14 2015 -0500
fix pktinfo for ipv4 packets
commit 8e338b842606a910a34a7ced09516a0cb097b449
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Thu Feb 19 11:48:55 2015 -0500
rework interface handling to prepare to learn ICE candidate
commit 09e365c1429d2a1d81126661df4749567f1e109d
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 18 16:24:42 2015 -0500
add some locking
commit 8fc7b75095d09f118a4febf1f3f7b75ed333751d
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 18 16:05:20 2015 -0500
extend logic in response to stun req and implement triggered checks
commit 35eeb04376c5a590f8fc42fcb1083a2fa7126e13
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 18 12:46:42 2015 -0500
handle ice/stun retransmits and timeouts
commit b5637565b659350fefb63034e4146ace8c6019b0
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Wed Feb 18 11:19:19 2015 -0500
first implementation of sending ICE checks
commit f0c1928c05a2c87fe23494367670207805c0b096
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 17 14:39:11 2015 -0500
preliminary list and loop for ICE checks
commit c38d6e22c18285a7fb87e5d7a00ac61cb5b7df02
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Tue Feb 17 12:00:24 2015 -0500
pair up candidates and prepare to run checks
commit d9559b4c5935ec602fdb801ecb0bd2158b39db65
Author: Richard Fuchs <rfuchs@sipwise.com>
Date: Fri Feb 13 15:36:29 2015 -0500
parse and remeber basic ICE attributes
pull/81/head
parent
fca4500dd0
commit
f99d6d4f42
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,208 @@
|
||||
#ifndef __ICE_H__
|
||||
#define __ICE_H__
|
||||
|
||||
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <glib.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include "str.h"
|
||||
#include "obj.h"
|
||||
#include "aux.h"
|
||||
#include "call.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#define MAX_COMPONENTS 2
|
||||
#define TIMER_RUN_INTERVAL 20 /* ms */
|
||||
#define STUN_RETRANSMIT_INTERVAL 100 /* ms, with exponential backoff */
|
||||
#define STUN_MAX_RETRANSMITS 7
|
||||
#define MAX_ICE_CANDIDATES 100
|
||||
|
||||
|
||||
|
||||
#define ICE_AGENT_COMPLETED 0x0002
|
||||
#define ICE_AGENT_CONTROLLING 0x0004
|
||||
#define ICE_AGENT_NOMINATING 0x0008
|
||||
|
||||
#define ICE_PAIR_FROZEN 0x0001
|
||||
#define ICE_PAIR_IN_PROGRESS 0x0002
|
||||
#define ICE_PAIR_FAILED 0x0004
|
||||
#define ICE_PAIR_SUCCEEDED 0x0008
|
||||
#define ICE_PAIR_NOMINATED 0x0010
|
||||
#define ICE_PAIR_LEARNED 0x0020
|
||||
#define ICE_PAIR_VALID 0x0040
|
||||
#define ICE_PAIR_TO_USE 0x0080
|
||||
#define ICE_PAIR_TRIGGERED 0x0100
|
||||
|
||||
#define PAIR_ISSET(p, f) bf_isset(&(p)->pair_flags, ICE_PAIR_ ## f)
|
||||
#define PAIR_SET(p, f) bf_set(&(p)->pair_flags, ICE_PAIR_ ## f)
|
||||
#define PAIR_SET2(p, f, g) bf_set(&(p)->pair_flags, ICE_PAIR_ ## f | ICE_PAIR_ ## g)
|
||||
#define PAIR_CLEAR(p, f) bf_clear(&(p)->pair_flags, ICE_PAIR_ ## f)
|
||||
#define PAIR_CLEAR2(p, f, g) bf_clear(&(p)->pair_flags, ICE_PAIR_ ## f | ICE_PAIR_ ## g)
|
||||
|
||||
#define AGENT_ISSET(p, f) bf_isset(&(p)->agent_flags, ICE_AGENT_ ## f)
|
||||
#define AGENT_ISSET2(p, f, g) bf_isset(&(p)->agent_flags, ICE_AGENT_ ## f | ICE_AGENT_ ## g)
|
||||
#define AGENT_SET(p, f) bf_set(&(p)->agent_flags, ICE_AGENT_ ## f)
|
||||
#define AGENT_SET2(p, f, g) bf_set(&(p)->agent_flags, ICE_AGENT_ ## f | ICE_AGENT_ ## g)
|
||||
#define AGENT_CLEAR(p, f) bf_clear(&(p)->agent_flags, ICE_AGENT_ ## f)
|
||||
#define AGENT_CLEAR2(p, f, g) bf_clear(&(p)->agent_flags, ICE_AGENT_ ## f | ICE_AGENT_ ## g)
|
||||
|
||||
|
||||
|
||||
struct local_interface;
|
||||
struct interface_address;
|
||||
struct packet_stream;
|
||||
struct call_media;
|
||||
struct call;
|
||||
struct stream_params;
|
||||
struct stun_attrs;
|
||||
|
||||
|
||||
|
||||
|
||||
enum ice_candidate_type {
|
||||
ICT_UNKNOWN = 0,
|
||||
ICT_HOST,
|
||||
ICT_SRFLX,
|
||||
ICT_PRFLX,
|
||||
ICT_RELAY,
|
||||
__ICT_LAST,
|
||||
};
|
||||
|
||||
enum ice_transport {
|
||||
ITP_UNKNOWN = 0,
|
||||
ITP_UDP,
|
||||
// ITP_TCP,
|
||||
};
|
||||
|
||||
struct ice_candidate {
|
||||
str foundation;
|
||||
unsigned long component_id;
|
||||
enum ice_transport transport;
|
||||
unsigned long priority;
|
||||
struct endpoint endpoint;
|
||||
enum ice_candidate_type type;
|
||||
struct in6_addr related_address;
|
||||
unsigned int related_port;
|
||||
};
|
||||
|
||||
struct ice_candidate_pair {
|
||||
struct ice_candidate *remote_candidate;
|
||||
struct interface_address *local_address;
|
||||
struct packet_stream *packet_stream;
|
||||
volatile unsigned int pair_flags;
|
||||
u_int32_t stun_transaction[3]; /* belongs to transaction_hash, thus agent->lock */
|
||||
unsigned int retransmit_ms;
|
||||
struct timeval retransmit;
|
||||
unsigned int retransmits;
|
||||
struct ice_agent *agent;
|
||||
u_int64_t pair_priority;
|
||||
int was_controlling:1,
|
||||
was_nominated:1;
|
||||
};
|
||||
|
||||
/* these are protected by the call's master_lock */
|
||||
struct ice_agent {
|
||||
struct obj obj;
|
||||
struct call *call; /* main reference */
|
||||
struct call_media *media;
|
||||
struct local_interface *local_interface;
|
||||
int desired_family;
|
||||
|
||||
mutex_t lock; /* for elements below. and call must be locked in R */
|
||||
/* lock order: in_lock first, then agent->lock */
|
||||
GQueue remote_candidates;
|
||||
GQueue candidate_pairs; /* for storage */
|
||||
GQueue triggered;
|
||||
GHashTable *candidate_hash;
|
||||
GHashTable *pair_hash;
|
||||
GHashTable *transaction_hash;
|
||||
GHashTable *foundation_hash;
|
||||
GTree *all_pairs;
|
||||
GQueue all_pairs_list; /* sorted through gtree */
|
||||
GTree *nominated_pairs; /* nominated by peer */
|
||||
GTree *succeeded_pairs; /* checked by us */
|
||||
GTree *valid_pairs; /* succeeded and nominated */
|
||||
unsigned int active_components;
|
||||
struct timeval start_nominating;
|
||||
|
||||
str ufrag[2]; /* 0 = remote, 1 = local */
|
||||
str pwd[2]; /* ditto */
|
||||
volatile unsigned int agent_flags;
|
||||
|
||||
struct timeval next_check; /* protected by ice_agents_timers_lock */
|
||||
struct timeval last_run; /* ditto */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
extern const unsigned int ice_type_preferences[];
|
||||
extern const char * const ice_type_strings[];
|
||||
|
||||
|
||||
|
||||
|
||||
void ice_init(void);
|
||||
|
||||
enum ice_candidate_type ice_candidate_type(const str *s);
|
||||
enum ice_transport ice_transport(const str *s);
|
||||
int ice_has_related(enum ice_candidate_type);
|
||||
void ice_foundation(struct interface_address *ifa);
|
||||
|
||||
void ice_agent_init(struct ice_agent **agp, struct call_media *media);
|
||||
void ice_update(struct ice_agent *, struct stream_params *);
|
||||
void ice_shutdown(struct ice_agent **);
|
||||
void ice_restart(struct ice_agent *);
|
||||
|
||||
void ice_candidates_free(GQueue *);
|
||||
void ice_remote_candidates(GQueue *, struct ice_agent *);
|
||||
|
||||
void ice_thread_run(void *);
|
||||
|
||||
int ice_request(struct packet_stream *, struct sockaddr_in6 *, struct in6_addr *, struct stun_attrs *);
|
||||
int ice_response(struct packet_stream *ps, struct sockaddr_in6 *src, struct in6_addr *dst,
|
||||
struct stun_attrs *attrs, u_int32_t transaction[3]);
|
||||
|
||||
/* returns 0 if ICE still has work to do, 1 otherwise */
|
||||
INLINE int ice_has_finished(struct call_media *media) {
|
||||
if (!media)
|
||||
return 1;
|
||||
if (!MEDIA_ISSET(media, ICE))
|
||||
return 1;
|
||||
if (!media->ice_agent)
|
||||
return 1;
|
||||
if (AGENT_ISSET(media->ice_agent, COMPLETED))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
INLINE unsigned int ice_type_preference(enum ice_candidate_type type) {
|
||||
if (type >= __ICT_LAST)
|
||||
return 0;
|
||||
return ice_type_preferences[type];
|
||||
}
|
||||
/* local_pref starts with 0 */
|
||||
INLINE u_int32_t ice_priority_pref(unsigned int type_pref, unsigned int local_pref, unsigned int component) {
|
||||
return type_pref << 24 | (65535 - local_pref) << 8 | (256 - component);
|
||||
}
|
||||
INLINE u_int32_t ice_priority(enum ice_candidate_type type, unsigned int local_pref, unsigned int component) {
|
||||
return ice_priority_pref(ice_type_preference(type), local_pref, component);
|
||||
}
|
||||
INLINE unsigned int ice_type_pref_from_prio(u_int32_t prio) {
|
||||
return (prio & 0xff000000) >> 24;
|
||||
}
|
||||
INLINE unsigned int ice_local_pref_from_prio(u_int32_t prio) {
|
||||
return 65535 - ((prio & 0xffff00) >> 8);
|
||||
}
|
||||
INLINE const char *ice_candidate_type_str(enum ice_candidate_type type) {
|
||||
if (type >= __ICT_LAST)
|
||||
return 0;
|
||||
return ice_type_strings[type];
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,91 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Socket;
|
||||
use Socket6;
|
||||
use Digest::SHA qw(hmac_sha1);
|
||||
use Digest::CRC qw(crc32);
|
||||
|
||||
my ($prio, $ip, $port, $username, $pwd) = @ARGV;
|
||||
|
||||
my $fd;
|
||||
my @dests = getaddrinfo($ip, $port, AF_UNSPEC, SOCK_DGRAM);
|
||||
while (@dests >= 5) {
|
||||
my ($fam, $type, $prot, $addr, $canon, @dests) = @dests;
|
||||
socket($fd, $fam, $type, $prot) or undef($fd), next;
|
||||
connect($fd, $addr) or undef($fd), next;
|
||||
last;
|
||||
}
|
||||
$fd or die($!);
|
||||
|
||||
my @rand = ('A' .. 'Z', 'a' .. 'z');
|
||||
my $ufrag = join('', (map {$rand[rand($#rand)]} (1 .. 10)));
|
||||
my $tract = join('', (map {$rand[rand($#rand)]} (1 .. 12)));
|
||||
my $control = rand() < .5;
|
||||
my $tbreak = int(rand(0xffffffff)) * int(rand(0xffffffff));
|
||||
|
||||
print("transaction: $tract\n");
|
||||
print("my username fragment: $ufrag\n");
|
||||
print("controll".($control?"ing":'ed')."\n");
|
||||
print("tie breaker: $tbreak\n");
|
||||
|
||||
|
||||
my $packet = '';
|
||||
$packet .= attr(6, "$username:$ufrag");
|
||||
$packet .= attr($control ? 0x802a : 0x8029, pack('Q', $tbreak));
|
||||
$packet .= attr(0x24, pack('N', $prio));
|
||||
$packet .= integrity();
|
||||
$packet .= fingerprint();
|
||||
$packet = header() . $packet;
|
||||
|
||||
send($fd, $packet, 0) or die $!;
|
||||
my $buf;
|
||||
recv($fd, $buf, 200, 0) or die;
|
||||
|
||||
my ($code, $length, $cookie, $tract2, $attrs) = unpack('nnN a12 a*', $buf);
|
||||
|
||||
if ($cookie == 0x2112A442 || $tract2 ne $tract) {
|
||||
printf("code: \%x\n", $code);
|
||||
while ($attrs ne '') {
|
||||
my ($type, $len, $cont);
|
||||
($type, $len, $attrs) = unpack('nn a*', $attrs);
|
||||
my $pad = 0;
|
||||
while ((($len + $pad) % 4) != 0) {
|
||||
$pad++;
|
||||
}
|
||||
($cont, $pad, $attrs) = unpack("a$len a$pad a*", $attrs);
|
||||
printf(" attr type: \%x\n", $type);
|
||||
print(" content: $cont\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
print("not stun: ".unpack('H*', $buf)."\n");
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
|
||||
sub attr {
|
||||
my ($type, $data) = @_;
|
||||
my $len = length($data);
|
||||
while ((length($data) % 4) != 0) {
|
||||
$data .= "\0";
|
||||
}
|
||||
return pack('nn a*', $type, $len, $data);
|
||||
}
|
||||
sub header {
|
||||
my ($add_length) = @_;
|
||||
$add_length ||= 0;
|
||||
return pack('nnN a12', 1, length($packet) + $add_length, 0x2112A442, $tract);
|
||||
}
|
||||
sub integrity {
|
||||
my $h = header(24);
|
||||
my $hmac = hmac_sha1($h.$packet, $pwd);
|
||||
return attr(8, $hmac);
|
||||
}
|
||||
sub fingerprint {
|
||||
my $h = header(8);
|
||||
my $crc = crc32($h.$packet);
|
||||
return attr(0x8028, pack('N', ($crc ^ 0x5354554e)));
|
||||
}
|
||||
@ -0,0 +1,204 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Socket;
|
||||
use Socket6;
|
||||
use Digest::SHA qw(hmac_sha1);
|
||||
use Digest::CRC qw(crc32);
|
||||
|
||||
my ($controlling, $port, $username, $pwd, @addresses) = @ARGV;
|
||||
|
||||
my %attrs = (
|
||||
6 => \&attr_un,
|
||||
8 => \&attr_mi,
|
||||
0x8028 => \&attr_fp,
|
||||
0x25 => \&attr_use,
|
||||
0x8029 => \&attr_controlled,
|
||||
0x802a => \&attr_controlling,
|
||||
);
|
||||
|
||||
my (@sockets, $packet, $tract, $code);
|
||||
|
||||
for my $addr (@addresses) {
|
||||
my ($fam, $pka, $sin, $meth) = addrparse($addr, $port);
|
||||
socket(my $fd, $fam, SOCK_DGRAM, 0) or die $!;
|
||||
bind($fd, $sin) or die $!;
|
||||
push(@sockets, {fd => $fd, fam => $fam, addr => $pka, sin => $sin, xormethod => $meth});
|
||||
}
|
||||
|
||||
while (1) {
|
||||
my $rin = '';
|
||||
for my $s (@sockets) {
|
||||
vec($rin, fileno($$s{fd}), 1) = 1;
|
||||
}
|
||||
|
||||
select($rin, undef, undef, 1);
|
||||
|
||||
for my $s (@sockets) {
|
||||
vec($rin, fileno($$s{fd}), 1) or next;
|
||||
|
||||
my $src = recv($$s{fd}, my $buf, 200, 0) or die $!;
|
||||
print("\npacket from " . addrdeparse($$s{fam}, $src) . " on ".
|
||||
addrdeparse($$s{fam}, $$s{sin}) . "\n");
|
||||
|
||||
my ($cmd, $len, $cookie, $attrs);
|
||||
($cmd, $len, $cookie, $tract, $attrs) = unpack('nnN a12 a*', $buf);
|
||||
|
||||
if ($cookie != 0x2112A442) {
|
||||
if ($buf =~ /^[\x14-\x3f]/s) {
|
||||
print("DTLS\n");
|
||||
}
|
||||
else {
|
||||
print("not stun: " . unpack("H*", $buf)."\n");
|
||||
}
|
||||
next;
|
||||
}
|
||||
$cmd == 1 or print("not stun request\n"), next;
|
||||
length($attrs) == $len or print("length mismatch\n"), next;
|
||||
|
||||
my ($list, $hash) = unpack_attrs($attrs);
|
||||
|
||||
$$list[$#$list]{name} eq 'fingerprint' or print("last attr not fingerprint\n"), next;
|
||||
$$list[$#$list-1]{name} eq 'message-integrity' or print("last but one attr not MI\n"), next;
|
||||
$$hash{username} or print("no username\n"), next;
|
||||
|
||||
$$hash{controlling} and print("is controlling\n");
|
||||
$$hash{controlled} and print("is controlled\n");
|
||||
$$hash{'use-candidate'} and print("nominated\n");
|
||||
|
||||
print("local username is $$hash{username}{split}[0], remote is $$hash{username}{split}[1]\n");
|
||||
|
||||
if ($$hash{controlling} && $controlling || $$hash{controlled} && !$controlling) {
|
||||
print("role conflict, replying with 487");
|
||||
$code = 0x0111; # binding error
|
||||
$packet = attr(0x9, pack('CCCC a16', 0, 0, 4, 87, 'Role conflict'));
|
||||
$packet .= integrity();
|
||||
$packet .= fingerprint();
|
||||
}
|
||||
else {
|
||||
$code = 0x101; # binding success
|
||||
my $xorattr = $$s{xormethod}($src);
|
||||
$packet = attr(0x20, $xorattr);
|
||||
$packet .= integrity();
|
||||
$packet .= fingerprint();
|
||||
}
|
||||
|
||||
$packet = header() . $packet;
|
||||
|
||||
print("sending reply\n");
|
||||
send($$s{fd}, $packet, 0, $src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
exit;
|
||||
|
||||
sub xor4 {
|
||||
my ($src) = @_;
|
||||
my @a = unpack_sockaddr_in($src);
|
||||
return pack('nna4', 1, $a[0] ^ 0x2112, $a[1] ^ "\x21\x12\xa4\x42");
|
||||
}
|
||||
sub xor6 {
|
||||
my ($src) = @_;
|
||||
my @a = unpack_sockaddr_in6($src);
|
||||
return pack('nna16', 2, $a[0] ^ 0x2112,
|
||||
$a[1] ^ ("\x21\x12\xa4\x42" . $tract));
|
||||
}
|
||||
sub addrparse {
|
||||
my ($addr, $port) = @_;
|
||||
my $r = inet_pton(AF_INET, $addr);
|
||||
$r and return (AF_INET, $r, pack_sockaddr_in($port, $r), \&xor4);
|
||||
$r = inet_pton(AF_INET6, $addr);
|
||||
$r and return (AF_INET6, $r, pack_sockaddr_in6($port, $r), \&xor6);
|
||||
die;
|
||||
}
|
||||
sub addrdeparse {
|
||||
my ($fam, $sin) = @_;
|
||||
if ($fam == AF_INET) {
|
||||
my @up = unpack_sockaddr_in($sin);
|
||||
return inet_ntop(AF_INET, $up[1]) . ":$up[0]";
|
||||
}
|
||||
if ($fam == AF_INET6) {
|
||||
my @up = unpack_sockaddr_in6($sin);
|
||||
return '['.inet_ntop(AF_INET6, $up[1]) . "]:$up[0]";
|
||||
}
|
||||
die;
|
||||
}
|
||||
|
||||
sub attr_un {
|
||||
my ($cont) = @_;
|
||||
return {name => 'username', split => [$cont =~ /(.*):(.*)/]};
|
||||
}
|
||||
sub attr_mi {
|
||||
return {name => 'message-integrity'};
|
||||
}
|
||||
sub attr_fp {
|
||||
my ($cont) = @_;
|
||||
return {name => 'fingerprint', value => unpack('N', $cont)};
|
||||
}
|
||||
sub attr_use {
|
||||
return {name => 'use-candidate'};
|
||||
}
|
||||
sub attr_controlling {
|
||||
my ($cont) = @_;
|
||||
return {name => 'controlling', tiebreaker => unpack('Q', $cont)};
|
||||
}
|
||||
sub attr_controlled {
|
||||
my ($cont) = @_;
|
||||
return {name => 'controlled', tiebreaker => unpack('Q', $cont)};
|
||||
}
|
||||
|
||||
|
||||
sub unpack_attrs {
|
||||
my ($s) = @_;
|
||||
|
||||
my (@out, %out);
|
||||
while ($s ne '') {
|
||||
my ($type, $len, $cont);
|
||||
($type, $len, $s) = unpack('nn a*', $s);
|
||||
my $pad = 0;
|
||||
while ((($len + $pad) % 4) != 0) {
|
||||
$pad++;
|
||||
}
|
||||
($cont, $pad, $s) = unpack("a$len a$pad a*", $s);
|
||||
my $ins = {type => $type, len => $len, content => $cont,
|
||||
raw => pack('nna*a*', $type, $len, $cont, $pad)};
|
||||
push(@out, $ins);
|
||||
$out{$type} = $ins;
|
||||
|
||||
my $pars = $attrs{$type};
|
||||
$pars or next;
|
||||
|
||||
my $ai = $pars->($cont);
|
||||
%$ins = (%$ins, %$ai);
|
||||
$out{$$ins{name}} = $ins;
|
||||
}
|
||||
return (\@out, \%out);
|
||||
}
|
||||
|
||||
|
||||
sub attr {
|
||||
my ($type, $data) = @_;
|
||||
my $len = length($data);
|
||||
while ((length($data) % 4) != 0) {
|
||||
$data .= "\0";
|
||||
}
|
||||
return pack('nn a*', $type, $len, $data);
|
||||
}
|
||||
sub header {
|
||||
my ($add_length) = @_;
|
||||
$add_length ||= 0;
|
||||
return pack('nnN a12', $code, length($packet) + $add_length, 0x2112A442, $tract);
|
||||
}
|
||||
sub integrity {
|
||||
my $h = header(24);
|
||||
my $hmac = hmac_sha1($h.$packet, $pwd);
|
||||
return attr(8, $hmac);
|
||||
}
|
||||
sub fingerprint {
|
||||
my $h = header(8);
|
||||
my $crc = crc32($h.$packet);
|
||||
return attr(0x8028, pack('N', ($crc ^ 0x5354554e)));
|
||||
}
|
||||
Loading…
Reference in new issue