1 /**
2  * @file ice/util.c  ICE Utilities
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 #include <string.h>
7 #ifdef HAVE_SYS_TIME_H
8 #include <sys/time.h>
9 #endif
10 #ifndef WIN32
11 #include <time.h>
12 #endif
13 #include <re_types.h>
14 #include <re_fmt.h>
15 #include <re_mem.h>
16 #include <re_mbuf.h>
17 #include <re_list.h>
18 #include <re_tmr.h>
19 #include <re_sa.h>
20 #include <re_stun.h>
21 #include <re_sys.h>
22 #include <re_ice.h>
23 #include "ice.h"
24 
25 
26 #define DEBUG_MODULE "iceutil"
27 #define DEBUG_LEVEL 5
28 #include <re_dbg.h>
29 
30 
31 enum {
32 	CAND_PRIO_RELAY =   0,
33 	CAND_PRIO_SRFLX = 100,
34 	CAND_PRIO_PRFLX = 110,
35 	CAND_PRIO_HOST  = 126
36 };
37 
38 
39 static uint32_t type_prio(enum ice_cand_type type)
40 {
41 	switch (type) {
42 
43 	case ICE_CAND_TYPE_HOST:   return CAND_PRIO_HOST;
44 	case ICE_CAND_TYPE_SRFLX:  return CAND_PRIO_SRFLX;
45 	case ICE_CAND_TYPE_PRFLX:  return CAND_PRIO_PRFLX;
46 	case ICE_CAND_TYPE_RELAY:  return CAND_PRIO_RELAY;
47 	default: return 0;
48 	}
49 }
50 
51 
52 uint32_t ice_cand_calc_prio(enum ice_cand_type type, uint16_t local,
53 			    unsigned compid)
54 {
55 	return type_prio(type)<<24 | (uint32_t)local<<8 | (256 - compid);
56 }
57 
58 
59 /*
60  * g = controlling agent
61  * d = controlled agent
62 
63  pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0)
64 
65  */
66 uint64_t ice_calc_pair_prio(uint32_t g, uint32_t d)
67 {
68 	const uint64_t m = min(g, d);
69 	const uint64_t x = max(g, d);
70 
71 	return (m<<32) + 2*x + (g>d?1:0);
72 }
73 
74 
75 void ice_switch_local_role(struct icem *icem)
76 {
77 	enum ice_role new_role;
78 
79 	if (ICE_ROLE_CONTROLLING == icem->lrole)
80 		new_role = ICE_ROLE_CONTROLLED;
81 	else
82 		new_role = ICE_ROLE_CONTROLLING;
83 
84 	DEBUG_NOTICE("Switch local role from %s to %s\n",
85 		     ice_role2name(icem->lrole), ice_role2name(new_role));
86 
87 	icem->lrole = new_role;
88 
89 #if 0
90 	/* recompute pair priorities for all media streams */
91 	for (le = icem->le.list->head; le; le = le->next) {
92 		icem = le->data;
93 		icem_candpair_prio_order(&icem->checkl);
94 	}
95 #endif
96 }
97 
98 
99 /**
100  * Remove duplicate elements from list, preserving order
101  *
102  * @param list  Linked list
103  * @param uh    Unique handler (return object to remove)
104  *
105  * @return Number of elements removed
106  *
107  * @note:    O (n ^ 2)
108  */
109 uint32_t ice_list_unique(struct list *list, list_unique_h *uh)
110 {
111 	struct le *le1 = list_head(list);
112 	uint32_t n = 0;
113 
114 	while (le1 && le1 != list->tail) {
115 
116 		struct le *le2 = le1->next;
117 		void *data = NULL;
118 
119 		while (le2) {
120 
121 			data = uh(le1, le2);
122 
123 			le2 = le2->next;
124 
125 			if (!data)
126 				continue;
127 
128 			if (le1->data == data)
129 				break;
130 			else {
131 				data = mem_deref(data);
132 				++n;
133 			}
134 		}
135 
136 		le1 = le1->next;
137 
138 		if (data) {
139 			mem_deref(data);
140 			++n;
141 		}
142 	}
143 
144 	return n;
145 }
146