srt: add stream ID option
[vlc.git] / modules / access / srt_common.c
1 /*****************************************************************************
2  * srt_common.c: SRT (Secure Reliable Transport) access module
3  *****************************************************************************
4  *
5  * Copyright (C) 2019, Haivision Systems Inc.
6  *
7  * Author: Aaron Boxer <aaron.boxer@collabora.com>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "srt_common.h"
25
26 const char * const srt_key_length_names[] = { N_( "16 bytes" ), N_(
27         "24 bytes" ), N_( "32 bytes" ), };
28
29 typedef struct parsed_param {
30     char *key;
31     char *val;
32 } parsed_param_t;
33
34 static inline char*
35 find(char *str, char find)
36 {
37     str = strchr( str, find );
38     return str != NULL ? str + 1 : NULL;
39 }
40
41 /**
42  * Parse a query string into an array of key/value structs.
43  *
44  * The query string should be a null terminated string of parameters separated
45  * by a delimiter. Each parameter are checked for the equal sign character.
46  * If it appears in the parameter, it will be used as a null terminator
47  * and the part that comes after it will be the value of the parameter.
48  *
49  *
50  * param: query:         the query string to parse. The string will be modified.
51  * param: delimiter:      the character that separates the key/value pairs
52  *                      from each other.
53  * param: params:       an array of parsed_param structs to hold the result.
54  * param: max_params:     maximum number of parameters to parse.
55  *
56  * Return:                the number of parsed items. -1 if there was an error.
57  */
58 static int srt_url_parse_query(char *query, const char* delimiter,
59         parsed_param_t *params, int max_params)
60 {
61     int i = 0;
62     char *token = NULL;
63
64     if (!query || *query == '\0')
65         return -1;
66     if (!params || max_params == 0)
67         return 0;
68
69     token = strtok( query, delimiter );
70     while (token != NULL && i < max_params) {
71         params[i].key = token;
72         params[i].val = NULL;
73         if ((params[i].val = strchr( params[i].key, '=' )) != NULL) {
74             size_t val_len = strlen( params[i].val );
75
76             /* make key into a zero-delimited string */
77             *(params[i].val) = '\0';
78
79             /* make sure val is not empty */
80             if (val_len > 1) {
81                 params[i].val++;
82
83                 /* make sure key is not empty */
84                 if (params[i].key[0])
85                     i++;
86             };
87         }
88         token = strtok( NULL, delimiter );
89     }
90     return i;
91 }
92
93 bool srt_parse_url(char* url, srt_params_t* params)
94 {
95     char* query = NULL;
96     struct parsed_param local_params[32];
97     int num_params = 0;
98     int i = 0;
99     bool rc = false;
100
101     if (!url || !url[0] || !params)
102         return false;
103
104     /* initialize params */
105     params->latency = -1;
106     params->passphrase = NULL;
107     params->key_length = -1;
108     params->payload_size = -1;
109     params->bandwidth_overhead_limit = -1;
110     params->streamid = NULL;
111
112     /* Parse URL parameters */
113     query = find( url, '?' );
114     if (query) {
115         num_params = srt_url_parse_query( query, "&", local_params,
116                 sizeof(local_params) / sizeof(struct parsed_param) );
117         if (num_params > 0) {
118             rc = true;
119             for (i = 0; i < num_params; ++i) {
120                 char* val = local_params[i].val;
121                 if (!val)
122                     continue;
123
124                 if (strcmp( local_params[i].key, SRT_PARAM_LATENCY ) == 0) {
125                     int temp = atoi( val );
126                     if (temp >= 0)
127                         params->latency = temp;
128                 } else if (strcmp( local_params[i].key, SRT_PARAM_PASSPHRASE )
129                         == 0) {
130                     params->passphrase = val;
131                 } else if (strcmp( local_params[i].key, SRT_PARAM_STREAMID )
132                         == 0) {
133                     params->streamid = val;
134                 } else if (strcmp( local_params[i].key, SRT_PARAM_PAYLOAD_SIZE )
135                         == 0) {
136                     int temp = atoi( val );
137                     if (temp >= 0)
138                         params->payload_size = temp;
139                 } else if (strcmp( local_params[i].key, SRT_PARAM_KEY_LENGTH )
140                         == 0) {
141                     int temp = atoi( val );
142                     if (temp == srt_key_lengths[0] || temp == srt_key_lengths[1]
143                             || temp == srt_key_lengths[2]) {
144                         params->key_length = temp;
145                     }
146                 } else if (strcmp( local_params[i].key,
147                 SRT_PARAM_BANDWIDTH_OVERHEAD_LIMIT ) == 0) {
148                     int temp = atoi( val );
149                     if (temp >= 0)
150                         params->bandwidth_overhead_limit = temp;
151
152                 }
153             }
154         }
155     }
156
157     return rc;
158 }
159
160 int srt_set_socket_option(vlc_object_t *this, const char *srt_param,
161         SRTSOCKET u, SRT_SOCKOPT opt, const void *optval, int optlen)
162 {
163     int stat = 0;
164
165     stat = srt_setsockopt( u, 0, opt, optval, optlen );
166     if (stat)
167     msg_Err( this, "Failed to set socket option %s (reason: %s)", srt_param,
168             srt_getlasterror_str() );
169
170     return stat;
171 }
172