Skip to content

Commit

Permalink
Trice module (#283)
Browse files Browse the repository at this point in the history
  • Loading branch information
alfredh authored Mar 18, 2022
1 parent d53ca50 commit 30bb73f
Show file tree
Hide file tree
Showing 16 changed files with 3,961 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
- name: coverage check
run: |
min_cov="57.5"
min_cov="54.2"
cov=$(~/.local/bin/gcovr -r . -s | grep lines | awk '{ print $2 }' | sed 's/%//')
echo "Coverage: ${cov}% (min $min_cov%)"
exit $(echo "$cov < $min_cov" | bc -l)
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,16 @@ set(SRCS

src/trace/trace.c

src/trice/cand.c
src/trice/candpair.c
src/trice/chklist.c
src/trice/connchk.c
src/trice/lcand.c
src/trice/rcand.c
src/trice/stunsrv.c
src/trice/tcpconn.c
src/trice/trice.c

src/turn/chan.c
src/turn/perm.c
src/turn/turnc.c
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ MODULES += odict
MODULES += json
MODULES += rtmp
MODULES += shim
MODULES += trice

INSTALL := install
ifeq ($(DESTDIR),)
Expand Down
166 changes: 166 additions & 0 deletions include/re_trice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/**
* @file re_ice.h Interface to Interactive Connectivity Establishment (ICE)
*
* Copyright (C) 2010 Alfred E. Heggestad
*/


/** ICE Configuration */
struct trice_conf {
bool debug; /**< Enable ICE debugging */
bool trace; /**< Enable tracing of Connectivity
checks */
bool ansi; /**< Enable ANSI colors for debug
output */
bool enable_prflx; /**< Enable Peer-Reflexive candidates */
bool optimize_loopback_pairing;/**< Reduce candidate pairs when
using loopback addresses */
};

struct trice;
struct ice_lcand;
struct ice_candpair;
struct stun_conf;


typedef bool (ice_cand_recv_h)(struct ice_lcand *lcand,
int proto, void *sock, const struct sa *src,
struct mbuf *mb, void *arg);


/** Local candidate */
struct ice_lcand {
struct ice_cand_attr attr; /**< Base class (inheritance) */
struct le le; /**< List element */

/* Base-address only set for SRFLX, PRFLX, RELAY */
struct sa base_addr; /* IP-address of "base" candidate (optional) */

struct udp_sock *us;
struct udp_helper *uh;
struct tcp_sock *ts; /* TCP for simultaneous-open or passive. */
char ifname[32]; /**< Network interface, for diagnostics */
int layer;
ice_cand_recv_h *recvh;
void *arg;

// todo: remove
struct trice *icem; /* parent */

struct {
size_t n_tx;
size_t n_rx;
} stats;
};

/** Remote candidate */
struct ice_rcand {
struct ice_cand_attr attr; /**< Base class (inheritance) */
struct le le; /**< List element */
};


/** Defines a candidate pair */
struct ice_candpair {
struct le le; /**< List element */
struct ice_lcand *lcand; /**< Local candidate */
struct ice_rcand *rcand; /**< Remote candidate */
enum ice_candpair_state state;/**< Candidate pair state */
uint64_t pprio; /**< Pair priority */
//bool def; /**< Default flag */
bool valid; /**< Valid flag */
bool nominated; /**< Nominated flag */
bool estab;
bool trigged;
int err; /**< Saved error code, if failed */
uint16_t scode; /**< Saved STUN code, if failed */

struct tcp_conn *tc;

struct ice_tcpconn *conn; /* the TCP-connection used */
};


typedef void (trice_estab_h)(struct ice_candpair *pair,
const struct stun_msg *msg, void *arg);


typedef void (trice_failed_h)(int err, uint16_t scode,
struct ice_candpair *pair, void *arg);


int trice_alloc(struct trice **icemp, const struct trice_conf *conf,
enum ice_role role, const char *lufrag, const char *lpwd);
int trice_set_remote_ufrag(struct trice *icem, const char *rufrag);
int trice_set_remote_pwd(struct trice *icem, const char *rpwd);
int trice_set_software(struct trice *icem, const char *sw);
int trice_set_role(struct trice *trice, enum ice_role role);
enum ice_role trice_local_role(const struct trice *icem);
int trice_debug(struct re_printf *pf, const struct trice *icem);
struct trice_conf *trice_conf(struct trice *icem);


/* Candidates (common) */
int trice_cand_print(struct re_printf *pf, const struct ice_cand_attr *cand);
enum ice_tcptype ice_tcptype_reverse(enum ice_tcptype type);
const char *ice_tcptype_name(enum ice_tcptype tcptype);
enum ice_cand_type ice_cand_type_base(enum ice_cand_type type);


/* Local candidates */
int trice_lcand_add(struct ice_lcand **lcandp, struct trice *icem,
unsigned compid, int proto, uint32_t prio,
const struct sa *addr, const struct sa *base_addr,
enum ice_cand_type type, const struct sa *rel_addr,
enum ice_tcptype tcptype,
void *sock, int layer);
struct list *trice_lcandl(const struct trice *icem);
struct ice_lcand *trice_lcand_find(struct trice *icem,
enum ice_cand_type type,
unsigned compid, int proto,
const struct sa *addr);
struct ice_lcand *trice_lcand_find2(const struct trice *icem,
enum ice_cand_type type, int af);
void *trice_lcand_sock(struct trice *icem, const struct ice_lcand *lcand);
void trice_lcand_recv_packet(struct ice_lcand *lcand,
const struct sa *src, struct mbuf *mb);


/* Remote candidate */
struct list *trice_rcandl(const struct trice *icem);
int trice_rcand_add(struct ice_rcand **rcandp, struct trice *icem,
unsigned compid, const char *foundation, int proto,
uint32_t prio, const struct sa *addr,
enum ice_cand_type type, enum ice_tcptype tcptype);
struct ice_rcand *trice_rcand_find(struct trice *icem, unsigned compid,
int proto, const struct sa *addr);


/* ICE Candidate pairs */
struct list *trice_checkl(const struct trice *icem);
struct list *trice_validl(const struct trice *icem);
struct ice_candpair *trice_candpair_find_state(const struct list *lst,
enum ice_candpair_state state);
int trice_candpair_debug(struct re_printf *pf, const struct ice_candpair *cp);
int trice_candpairs_debug(struct re_printf *pf, bool ansi_output,
const struct list *list);


/* ICE checklist */
void trice_checklist_set_waiting(struct trice *icem);
int trice_checklist_start(struct trice *icem, struct stun *stun,
uint32_t interval,
trice_estab_h *estabh, trice_failed_h *failh,
void *arg);
void trice_checklist_stop(struct trice *icem);
bool trice_checklist_isrunning(const struct trice *icem);
bool trice_checklist_iscompleted(const struct trice *icem);


/* ICE Conncheck */
int trice_conncheck_send(struct trice *icem, struct ice_candpair *pair,
bool use_cand);

/* Port range */
int trice_set_port_range(struct trice *trice,
uint16_t min_port, uint16_t max_port);
109 changes: 109 additions & 0 deletions src/trice/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
ICE-NOTES:
---------



----------------------------------
Application layer:

- Can handle any modes (Full, Ice, Trickle)
- Can implement any nomination-type (regular, aggressive)
- Can encode/decode SDP attributes
- Must gather all candidates (including STUN/TURN servers)
- Application can choose the Default Local Candidate
- Application can choose the Default Remote Candidate
- Can measure RTT end-to-end
- Can apply a STUN consent timer on top of ICE
- the application should have the freedom to choose any selected candidate-pair
- can install Keep-Alive timer (Binding Indication) for any pairs
- can install a consent timer for any pair


----------------------------------
ICE layer:

- All modes (Full-ICE and Trickle-ICE) are implemented
- ICE-lite is NOT supported
- agnostic to modes (Full, Trickle)
- agnostic to nomination-type (regular, aggressive)
- SDP encoding and decoding of ICE-relavant attributes
- can handle between 1 and 2 components per media-stream
- gathering: No candidate gathering, must be done in App
- agnostic to transport protocol (should handle both UDP and TCP)
- rel-addr (related address) is supported, but it is not used in the logic
- ICE-stack does not choose the Default Local Candidate
- ICE-stack does not choose the Default Remote Candidate
- no TURN client
- Each local candidate can have its own listen address/port. Yes
- Support for UDP-transport
- Support for TCP-transport
- Support for IPv4 and IPv6
- modular design with building blocks.
- check all components before calling estabh ? no.
- no support for "default" candidate/candidate-pair
- component object: NO
- selected pair: NO
- must be able to support custom UDP/TCP-transport via helpers


----------------------------------
Interop:

OK - Firefox 31.0
OK - Firefox 35.0
OK - Firefox 36.0
OK - Chrome 41
OK - Chrome 58


TODO:

done - remove ICE-lite mode
done - remove rel-addr from ICE-code
done - interop testing with Chrome
done - interop testing with Firefox - seems to be working with 31.0
done - Firefox: test with trickling candidates over Websock
done - add support for TCP-candidates (test with Chrome)
done - make a new test-client (reicec) and test on a public server
done - do we need to support LITE at all? No.
done - split EOC flag into local_eoc and remote_eoc
done - send trigged request from stunsrv
done - new module "icesdp" for SDP encoding/decoding
done - add a new module "shim" (RFC 4571)
- ICE module should be Conncheck-only, no data-transport
- test_ice_tcp: S-O not working on Linux
done - check when adding PRFLX that EOC-flag is set/unset (not needed)
done - move use_cand flag to checklist_start/send_conncheck ?
- verify that APP can grab udp/tcp-sock
- consider moving pacing-logic to application?




Architecture Diagram:
--------------------



```
.-------. .-------.
| App | | App |
'-------' '-------'
| | \
| .--------. | |
+--------+ STUN +--------+ |
| '--------' | | "ICE-layer"
| .-------. |
| | SHIM | |
| '-------' |
| | /
.-------. .-------.
| UDP | | TCP |
'-------' '-------'
| |
! !
```
88 changes: 88 additions & 0 deletions src/trice/cand.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* @file cand.c Common ICE Candidates
*
* Copyright (C) 2010 Alfred E. Heggestad
*/
#include <string.h>
#include <re_types.h>
#include <re_fmt.h>
#include <re_mem.h>
#include <re_mbuf.h>
#include <re_list.h>
#include <re_tmr.h>
#include <re_sa.h>
#include <re_net.h>
#include <re_sys.h>
#include <re_stun.h>
#include <re_udp.h>
#include <re_tcp.h>
#include <re_ice.h>
#include <re_trice.h>
#include "trice.h"


const char *ice_tcptype_name(enum ice_tcptype tcptype)
{
switch (tcptype) {

case ICE_TCP_ACTIVE: return "active";
case ICE_TCP_PASSIVE: return "passive";
case ICE_TCP_SO: return "so";
default: return "???";
}
}


/*
Local Remote
Candidate Candidate
---------------------------
tcp-so tcp-so
tcp-active tcp-passive
tcp-passive tcp-active
*/
enum ice_tcptype ice_tcptype_reverse(enum ice_tcptype type)
{
switch (type) {

case ICE_TCP_SO: return ICE_TCP_SO;
case ICE_TCP_ACTIVE: return ICE_TCP_PASSIVE;
case ICE_TCP_PASSIVE: return ICE_TCP_ACTIVE;
default: return (enum ice_tcptype)-1;
}
}


enum ice_cand_type ice_cand_type_base(enum ice_cand_type type)
{
switch (type) {

case ICE_CAND_TYPE_HOST: return ICE_CAND_TYPE_HOST;
case ICE_CAND_TYPE_SRFLX: return ICE_CAND_TYPE_HOST;
case ICE_CAND_TYPE_PRFLX: return ICE_CAND_TYPE_HOST;
case ICE_CAND_TYPE_RELAY: return ICE_CAND_TYPE_RELAY;
default: return type;
}
}


int trice_cand_print(struct re_printf *pf, const struct ice_cand_attr *cand)
{
int err = 0;

if (!cand)
return 0;

err |= re_hprintf(pf, "%s|%s", ice_cand_type2name(cand->type),
net_proto2name(cand->proto));

if (cand->proto == IPPROTO_TCP) {

err |= re_hprintf(pf, ".%s", ice_tcptype_name(cand->tcptype));
}

err |= re_hprintf(pf, "|%J", &cand->addr);

return err;
}
Loading

0 comments on commit 30bb73f

Please sign in to comment.