Skip to content

Commit 6751ff7

Browse files
committed
MT#55283 support dict/list for rtpp_flags
Change-Id: Ic9cd39ce771eb5767bb970af5aa438e692a61586
1 parent 4f54910 commit 6751ff7

File tree

4 files changed

+450
-12
lines changed

4 files changed

+450
-12
lines changed

daemon/control_ng_flags_parser.c

Lines changed: 184 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,188 @@ static bool str_key_val_prefix(const str * p, const char * q,
6464
return true;
6565
}
6666

67-
static bool dummy_is_list(parser_arg a) {
68-
return false;
67+
static inline bool skip_char(str *s, char c) {
68+
if (s->len == 0 || s->s[0] != c)
69+
return false;
70+
str_shift(s, 1);
71+
return true;
72+
}
73+
static inline void skip_chars(str *s, char c) {
74+
while (skip_char(s, c));
75+
}
76+
77+
static int rtpp_is_dict_list(str *a) {
78+
str list = *a;
79+
if (!skip_char(&list, '['))
80+
return 0;
81+
// check contents
82+
if (list.len == 0)
83+
return 0; // unexpected end of string
84+
if (list.s[0] == '[')
85+
return 1; // contains sub-list, must be a list
86+
// inspect first element for 'key='
87+
str key, val;
88+
if (!get_key_val(&key, &val, &list))
89+
return 0; // nothing to read
90+
if (val.len)
91+
return 2; // is a dict
92+
return 1; // is a list
93+
}
94+
95+
static bool rtpp_is_list(rtpp_pos *a) {
96+
return rtpp_is_dict_list(&a->cur) == 1;
6997
}
70-
static str *dummy_get_str(parser_arg a, str *b) {
71-
*b = *a.str;
98+
static bool rtpp_is_dict(rtpp_pos *a) {
99+
return rtpp_is_dict_list(&a->cur) == 2;
100+
}
101+
static str *rtpp_get_str(rtpp_pos *a, str *b) {
102+
if (rtpp_is_dict_list(&a->cur) != 0)
103+
return NULL;
104+
if (a->cur.len == 0)
105+
return NULL;
106+
*b = a->cur;
72107
return b;
73108
}
109+
static long long rtpp_get_int_str(rtpp_pos *a, long long def) {
110+
str s;
111+
if (!rtpp_get_str(a, &s))
112+
return def;
113+
return str_to_i(&s, def);
114+
}
115+
static bool rtpp_dict_list_end_rewind(rtpp_pos *pos) {
116+
// check for dict/list end, which is only valid if it doesn't also start one
117+
if (pos->cur.len == 0 || pos->cur.s[0] == '[' || pos->cur.s[pos->cur.len - 1] != ']')
118+
return false;
119+
120+
pos->cur.len--;
121+
// remove any extra closing bracket, and return them to the remainder for
122+
// the upper level function to parse
123+
while (pos->cur.len && pos->cur.s[pos->cur.len - 1] == ']') {
124+
pos->cur.len--;
125+
pos->remainder.s--;
126+
pos->remainder.len++;
127+
// we might be on a space or something - go to the actual bracket, which must
128+
// be there somewhere
129+
while (pos->remainder.s[0] != ']') {
130+
pos->remainder.s--;
131+
pos->remainder.len++;
132+
}
133+
}
134+
135+
return true;
136+
}
137+
static bool rtpp_dict_list_closing(rtpp_pos *pos) {
138+
if (pos->cur.s[0] != ']')
139+
return false;
140+
141+
str_shift(&pos->cur, 1);
142+
// anything left in the string, return it to the remainder
143+
pos->remainder.len += pos->remainder.s - pos->cur.s;
144+
pos->remainder.s = pos->cur.s;
145+
146+
return true;
147+
}
148+
static void rtpp_list_iter(const ng_parser_t *parser, rtpp_pos *pos,
149+
void (*str_callback)(str *key, unsigned int, helper_arg),
150+
void (*item_callback)(const ng_parser_t *, parser_arg, helper_arg), helper_arg arg)
151+
{
152+
// list opener
153+
if (!skip_char(&pos->cur, '['))
154+
return;
155+
156+
unsigned int idx = 0;
157+
158+
while (true) {
159+
skip_chars(&pos->cur, ' ');
160+
if (!pos->cur.len)
161+
goto next; // empty token?
162+
163+
// list closing?
164+
if (rtpp_dict_list_closing(pos))
165+
break;
166+
167+
// does it start another list or dict?
168+
if (pos->cur.s[0] == '[') {
169+
if (item_callback)
170+
item_callback(parser, pos, arg);
171+
goto next;
172+
}
173+
174+
// guess it's a string token
175+
// does it end the list?
176+
bool end = rtpp_dict_list_end_rewind(pos);
177+
178+
if (pos->cur.len == 0)
179+
break; // nothing left
180+
181+
if (str_callback)
182+
str_callback(&pos->cur, idx++, arg);
183+
if (end)
184+
break;
185+
goto next;
186+
187+
next:
188+
// find next token in remainder, put in `cur`
189+
if (!str_token_sep(&pos->cur, &pos->remainder, ' '))
190+
break;
191+
}
192+
}
193+
static bool rtpp_dict_iter(const ng_parser_t *parser, rtpp_pos *pos,
194+
void (*callback)(const ng_parser_t *, str *, parser_arg, helper_arg),
195+
helper_arg arg)
196+
{
197+
// list opener
198+
if (!skip_char(&pos->cur, '['))
199+
return false;
200+
201+
while (true) {
202+
skip_chars(&pos->cur, ' ');
203+
if (!pos->cur.len)
204+
goto next; // empty token?
205+
206+
// dict closing?
207+
if (rtpp_dict_list_closing(pos))
208+
break;
209+
210+
str key;
211+
if (!str_token(&key, &pos->cur, '=')) {
212+
ilog(LOG_ERR, "Entry in dictionary without equals sign ('" STR_FORMAT "'), aborting",
213+
STR_FMT(&pos->cur));
214+
break;
215+
}
216+
217+
// guess it's a string token
218+
// does it end the dict?
219+
bool end = rtpp_dict_list_end_rewind(pos);
220+
221+
if (pos->cur.len == 0)
222+
break; // nothing left
223+
224+
callback(parser, &key, pos, arg);
225+
if (end)
226+
break;
227+
goto next;
228+
229+
next:
230+
// find next token in remainder, put in `cur`
231+
if (!str_token_sep(&pos->cur, &pos->remainder, ' '))
232+
break;
233+
}
234+
235+
return true;
236+
}
237+
static bool rtpp_is_int(rtpp_pos *pos) {
238+
return false;
239+
}
74240

75241
const ng_parser_t dummy_parser = {
76-
.is_list = dummy_is_list,
77-
.get_str = dummy_get_str,
242+
.is_list = rtpp_is_list,
243+
.is_dict = rtpp_is_dict,
244+
.is_int = rtpp_is_int,
245+
.list_iter = rtpp_list_iter,
246+
.dict_iter = rtpp_dict_iter,
247+
.get_str = rtpp_get_str,
248+
.get_int_str = rtpp_get_int_str,
78249
};
79250

80251
static bool parse_codec_to_dict(str * key, str * val, const char *cmp1, const char *cmp2,
@@ -158,8 +329,7 @@ void parse_rtpp_flags(const str * rtpp_flags, sdp_ng_flags *out)
158329
while (remainder.len)
159330
{
160331
/* skip spaces */
161-
while (remainder.len && remainder.s[0] == ' ')
162-
str_shift(&remainder, 1);
332+
skip_chars(&remainder, ' ');
163333

164334
/* set key and val */
165335
if (!get_key_val(&key, &val, &remainder))
@@ -229,7 +399,7 @@ void parse_rtpp_flags(const str * rtpp_flags, sdp_ng_flags *out)
229399
if (!val.s && str_eq(&key, "RTP/SAVPF"))
230400
transport = 0x103;
231401
/* direction */
232-
else if (str_eq(&key, "direction"))
402+
else if (str_eq(&key, "direction") && rtpp_is_dict_list(&val) == 0)
233403
rtpp_direction_flag(out, &direction_flag, &val);
234404
else
235405
goto generic;
@@ -258,8 +428,11 @@ void parse_rtpp_flags(const str * rtpp_flags, sdp_ng_flags *out)
258428
if (!val.len)
259429
call_ng_flags_flags(&key, 0, out);
260430
/* generic flags with value, but no particular processing */
261-
else
262-
call_ng_main_flags(&dummy_parser, &key, &val, out);
431+
else {
432+
rtpp_pos pos = { .cur = val, .remainder = remainder };
433+
call_ng_main_flags(&dummy_parser, &key, &pos, out);
434+
remainder = pos.remainder;
435+
}
263436

264437
next:;
265438
}

docs/ng_control_protocol.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ When the flags are passed to rtpengine, they are formated as following:
121121

122122
{ "rtpp_flags": "replace-origin via-branch=auto-next strict-source label=callee OSRTP-accept transport-protocol=RTP/AVP address-family=IP4" }
123123

124+
Lists and dictionaries are supported in this format using square brackets `[ ]`, for example:
125+
126+
{ "rtpp_flags": "via-branch=auto-next OSRTP=[accept] codec=[transcode=[PCMA PCMU] accept=[AMR-WB AMR] strip=[EVS]]" }
127+
124128
Regardless whether the flags parsing is done by the module or daemon,
125129
a functional behavior remains the same and has no difference in terms of SDP processing.
126130

include/types.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,15 @@ typedef struct ng_command_ctx ng_command_ctx_t;
4343

4444
typedef struct bencode_item bencode_item_t;
4545

46+
typedef struct {
47+
str cur;
48+
str remainder;
49+
} rtpp_pos;
50+
4651
typedef union {
4752
bencode_item_t *benc;
4853
JsonNode *json;
49-
str *str;
54+
rtpp_pos *rtpp;
5055
void *gen;
5156
} parser_arg __attribute__ ((__transparent_union__));
5257

0 commit comments

Comments
 (0)