[vlc-devel] [PATCH] srt: parse srt parameters from url

Thomas Guillem thomas at gllm.fr
Thu Mar 7 09:18:09 CET 2019


The classical use case is:

- Users enter an url (without password)
- VLC access module try to open it without any credential
- In case of success: nothing to do<
- If it fail: VLC ask users for credentials and try to re-open the url

On Wed, Mar 6, 2019, at 23:25, Aaron Boxer wrote:
> 
> 
> On Wed, Mar 6, 2019 at 12:11 PM Thomas Guillem <thomas at gllm.fr> wrote:
>> __
>> 
>> On Wed, Mar 6, 2019, at 17:59, Aaron Boxer wrote:
>>> 
>>> 
>>> On Wed, Mar 6, 2019 at 10:39 AM Thomas Guillem <thomas at gllm.fr> wrote:
>>>> __
>>>> 
>>>> On Wed, Mar 6, 2019, at 16:34, Aaron Boxer wrote:
>>>>> Thank you, Tristan. So, I see that vlc_credential API is a way of extracting the user credentials from the URL.
>>>>> But, there would still be the issue of credentials being displayed in window, logs etc, as mentioned by Remi ?
>>>> 
>>>> Hello,
>>>> This API handle credential from URL yes, but it's not its main purpose. This API handle interaction with the user (from a dialog generally) to ask for a password. This API will also save the password in VLC internal memory keystore and/or in the OS one (kwallet and co) if the user want to.
>>> 
>>> Thanks. SRT stream doesn't require a user name + password. It only has a passphrase. So, how would the credentials work in this case ?
>> 
>> No, but this can be fixed.
>> 
>> in vlc_keystore.h/keystore.c:
>> 
>> - vlc_credential_init(vlc_credential *p_credential, const vlc_url_t *p_url);
>> + vlc_credential_init(vlc_credential *p_credential, const vlc_url_t *p_url, bool ask_user);
>> 
>> in vlc_dialog.h/dialog.c
>> Fix vlc_dialog_wait_login_va() to work with a NULL ppsz_username
>> 
>> in qt gui:
>> handle the NULL username to display only one text dialog.
> 
> 
> Thanks. But, I still don't see how the credentials can help.
> 
> Here is the workflow:
> 
> 1. user opens Media -> Open Network Stream
> 2. user enters URL
> 3. user enters passphrase, which is stored in credentials
> 4. ....
> 5. static int Open(vlc_object_t *p_this) method called in srt.c
> 
> So, after step 5, how would I get the passphrase stored for this url ?
> 
> 
> 
>> 
>> 
>>> 
>>>> 
>>>> 
>>>>> 
>>>>> On Wed, Mar 6, 2019 at 10:20 AM Tristan Matthews <tmatth at videolan.org> wrote:
>>>>>> On Wed, Mar 6, 2019 at 10:04 AM Aaron Boxer <boxerab at gmail.com> wrote:
>>>>>> >
>>>>>> > Thanks, Remi. Is there another better way of getting a user-configured passphrase to the srt module ?
>>>>>> 
>>>>>> I think you want the vlc_credential API, see e.g.,
>>>>>> https://git.videolan.org/?p=vlc.git;a=blob;f=modules/access/http.c;h=56d75687e27f10a6c1ef33cd32178dcc857e4136;hb=HEAD#l304
>>>>>> 
>>>>>> Best,
>>>>>> -t
>>>>>> 
>>>>>> > On Wed, Mar 6, 2019 at 5:57 AM Rémi Denis-Courmont <remi at remlab.net> wrote:
>>>>>> >>
>>>>>> >> Hi,
>>>>>> >>
>>>>>> >> Passing passwords in URLs is well-documented as a terrible idea. In VLC's case, the passphrase will show up in the OSD title, window title, logs, etc...
>>>>>> >>
>>>>>> >> Le 5 mars 2019 23:42:14 GMT+02:00, Aaron Boxer <boxerab at gmail.com> a écrit :
>>>>>> >>>
>>>>>> >>> Parse pass phrase and latency from url for incoming srt stream
>>>>>> >>>
>>>>>> >>>
>>>>>> >>> diff --git a/modules/access/srt.c b/modules/access/srt.c
>>>>>> >>> index d8d8cbe659..55c0efc201 100644
>>>>>> >>> --- a/modules/access/srt.c
>>>>>> >>> +++ b/modules/access/srt.c
>>>>>> >>> @@ -37,6 +37,9 @@
>>>>>> >>>
>>>>>> >>> #include <srt/srt.h>
>>>>>> >>>
>>>>>> >>> +const char* SRT_PARAM_PASSPHRASE = "passphrase";
>>>>>> >>> +const char* SRT_PARAM_LATENCY = "latency";
>>>>>> >>> +
>>>>>> >>> /* libsrt defines default packet size as 1316 internally
>>>>>> >>> * so srt module takes same value. */
>>>>>> >>> #define SRT_DEFAULT_CHUNK_SIZE 1316
>>>>>> >>> @@ -70,6 +73,85 @@ typedef struct
>>>>>> >>> int i_chunks; /* Number of chunks to allocate in the next read */
>>>>>> >>> } stream_sys_t;
>>>>>> >>>
>>>>>> >>> +
>>>>>> >>> +
>>>>>> >>> +struct parsed_param {
>>>>>> >>> + char *key;
>>>>>> >>> + char *val;
>>>>>> >>> +};
>>>>>> >>> +
>>>>>> >>> +static inline char *
>>>>>> >>> +find(char *str, char find)
>>>>>> >>> +{
>>>>>> >>> + str = strchr(str, find);
>>>>>> >>> + if (NULL == str) {
>>>>>> >>> + return NULL;
>>>>>> >>> + }
>>>>>> >>> + return str + 1;
>>>>>> >>> +}
>>>>>> >>> +
>>>>>> >>> +static inline char *
>>>>>> >>> +find_query(char *str)
>>>>>> >>> +{
>>>>>> >>> + return find(str, '?');
>>>>>> >>> +}
>>>>>> >>> +
>>>>>> >>> +/**
>>>>>> >>> + * Parse a query string into an array of key/value structs.
>>>>>> >>> + *
>>>>>> >>> + * The query string should be a null terminated string of parameters separated by
>>>>>> >>> + * a delimiter. Each parameter are checked for the equal sign character. If it
>>>>>> >>> + * appears in the parameter, it will be used as a null terminator and the part
>>>>>> >>> + * that comes after it will be the value of the parameter.
>>>>>> >>> + *
>>>>>> >>> + *
>>>>>> >>> + * param: query: the query string to parse. The string will be modified.
>>>>>> >>> + * param: delimiter: the character that separates the key/value pairs from each other.
>>>>>> >>> + * param: params: an array of parsed_param structs to hold the result.
>>>>>> >>> + * param: max_params: maximum number of parameters to parse.
>>>>>> >>> + *
>>>>>> >>> + * Return: the number of parsed items. -1 if there was an error.
>>>>>> >>> + */
>>>>>> >>> +static int
>>>>>> >>> +srt_url_parse_query(char *query, char delimiter, struct parsed_param *params, int max_params)
>>>>>> >>> +{
>>>>>> >>> + int i = 0;
>>>>>> >>> +
>>>>>> >>> + if (!query || *query == '\0')
>>>>>> >>> + {
>>>>>> >>> + return -1;
>>>>>> >>> + }
>>>>>> >>> + if (!params || max_params == 0)
>>>>>> >>> + {
>>>>>> >>> + return 0;
>>>>>> >>> + }
>>>>>> >>> +
>>>>>> >>> + params[i++].key = query;
>>>>>> >>> + while (i < max_params && NULL != (query = strchr(query, delimiter)))
>>>>>> >>> + {
>>>>>> >>> + *query = '\0';
>>>>>> >>> + params[i].key = ++query;
>>>>>> >>> + params[i].val = NULL;
>>>>>> >>> +
>>>>>> >>> + /* Go back and split previous param if one exists */
>>>>>> >>> + if (i > 0)
>>>>>> >>> + {
>>>>>> >>> + if ((params[i - 1].val = strchr(params[i - 1].key, '=')) != NULL)
>>>>>> >>> + {
>>>>>> >>> + *(params[i - 1].val)++ = '\0';
>>>>>> >>> + }
>>>>>> >>> + }
>>>>>> >>> + i++;
>>>>>> >>> + }
>>>>>> >>> + /* Go back and split last param */
>>>>>> >>> + if ((params[i - 1].val = strchr(params[i - 1].key, '=')) != NULL)
>>>>>> >>> + {
>>>>>> >>> + *(params[i - 1].val)++ = '\0';
>>>>>> >>> + }
>>>>>> >>> + return i;
>>>>>> >>> +}
>>>>>> >>> +
>>>>>> >>> +
>>>>>> >>> static void srt_wait_interrupted(void *p_data)
>>>>>> >>> {
>>>>>> >>> stream_t *p_stream = p_data;
>>>>>> >>> @@ -115,9 +197,11 @@ static int Control(stream_t *p_stream, int i_query, va_list args)
>>>>>> >>>
>>>>>> >>> static bool srt_schedule_reconnect(stream_t *p_stream)
>>>>>> >>> {
>>>>>> >>> - int i_latency;
>>>>>> >>> + int i_latency=-1;
>>>>>> >>> int stat;
>>>>>> >>> char *psz_passphrase = NULL;
>>>>>> >>> + bool parsed_passphrase = false;
>>>>>> >>> + char *url = NULL;
>>>>>> >>>
>>>>>> >>> struct addrinfo hints = {
>>>>>> >>> .ai_socktype = SOCK_DGRAM,
>>>>>> >>> @@ -153,6 +237,38 @@ static bool srt_schedule_reconnect(stream_t *p_stream)
>>>>>> >>> goto out;
>>>>>> >>> }
>>>>>> >>>
>>>>>> >>> + /* Parse URL parameters */
>>>>>> >>> + if (p_stream->psz_url && strlen(p_stream->psz_url) < 512)
>>>>>> >>> + {
>>>>>> >>> + char* query = NULL;
>>>>>> >>> + struct parsed_param params[32];
>>>>>> >>> + int num_params = 0;
>>>>>> >>> + int i=0;
>>>>>> >>> + size_t url_size = strlen(p_stream->psz_url)+1;
>>>>>> >>> +
>>>>>> >>> + url = malloc(url_size);
>>>>>> >>> + url[url_size-1] = 0;
>>>>>> >>> + strcpy(url, p_stream->psz_url);
>>>>>> >>> + query = find_query(url);
>>>>>> >>> + if (query)
>>>>>> >>> + {
>>>>>> >>> + num_params = srt_url_parse_query(query,'&', params, sizeof(params)/sizeof(struct parsed_param) );
>>>>>> >>> + if (num_params > 0) {
>>>>>> >>> + for (i = 0; i < num_params; ++i)
>>>>>> >>> + {
>>>>>> >>> + if (strcmp(params[i].key, SRT_PARAM_PASSPHRASE) == 0)
>>>>>> >>> + {
>>>>>> >>> + psz_passphrase = params[i].val;
>>>>>> >>> + parsed_passphrase = true;
>>>>>> >>> + }
>>>>>> >>> + else if (strcmp(params[i].key, SRT_PARAM_LATENCY) == 0)
>>>>>> >>> + i_latency = atoi(params[i].val);
>>>>>> >>> + }
>>>>>> >>> + }
>>>>>> >>> + }
>>>>>> >>> + }
>>>>>> >>> +
>>>>>> >>> +
>>>>>> >>> /* Make SRT non-blocking */
>>>>>> >>> srt_setsockopt( p_sys->sock, 0, SRTO_SNDSYN,
>>>>>> >>> &(bool) { false }, sizeof( bool ) );
>>>>>> >>> @@ -168,11 +284,13 @@ static bool srt_schedule_reconnect(stream_t *p_stream)
>>>>>> >>> &(int) { 0 }, sizeof( int ) );
>>>>>> >>>
>>>>>> >>> /* Set latency */
>>>>>> >>> - i_latency = var_InheritInteger( p_stream, "latency" );
>>>>>> >>> + if (i_latency == -1)
>>>>>> >>> + i_latency = var_InheritInteger( p_stream, SRT_PARAM_LATENCY );
>>>>>> >>> srt_setsockopt( p_sys->sock, 0, SRTO_TSBPDDELAY,
>>>>>> >>> &i_latency, sizeof( int ) );
>>>>>> >>>
>>>>>> >>> - psz_passphrase = var_InheritString( p_stream, "passphrase" );
>>>>>> >>> + if (!psz_passphrase)
>>>>>> >>> + psz_passphrase = var_InheritString( p_stream, SRT_PARAM_PASSPHRASE );
>>>>>> >>> if ( psz_passphrase != NULL && psz_passphrase[0] != '\0')
>>>>>> >>> {
>>>>>> >>> int i_key_length = var_InheritInteger( p_stream, "key-length" );
>>>>>> >>> @@ -211,7 +329,11 @@ out:
>>>>>> >>> }
>>>>>> >>>
>>>>>> >>> freeaddrinfo( res );
>>>>>> >>> - free( psz_passphrase );
>>>>>> >>> + if (!parsed_passphrase)
>>>>>> >>> + {
>>>>>> >>> + free( psz_passphrase );
>>>>>> >>> + }
>>>>>> >>> + free(url);
>>>>>> >>>
>>>>>> >>> return !failed;
>>>>>> >>> }
>>>>>> >>> @@ -422,8 +544,8 @@ vlc_module_begin ()
>>>>>> >>> N_("SRT chunk size (bytes)"), NULL, true )
>>>>>> >>> add_integer( "poll-timeout", SRT_DEFAULT_POLL_TIMEOUT,
>>>>>> >>> N_("Return poll wait after timeout milliseconds (-1 = infinite)"), NULL, true )
>>>>>> >>> - add_integer( "latency", SRT_DEFAULT_LATENCY, N_("SRT latency (ms)"), NULL, true )
>>>>>> >>> - add_password("passphrase", "", N_("Password for stream encryption"), NULL)
>>>>>> >>> + add_integer( SRT_PARAM_LATENCY, SRT_DEFAULT_LATENCY, N_("SRT latency (ms)"), NULL, true )
>>>>>> >>> + add_password(SRT_PARAM_PASSPHRASE, "", N_("Password for stream encryption"), NULL)
>>>>>> >>> add_integer( "key-length", SRT_DEFAULT_KEY_LENGTH,
>>>>>> >>> SRT_KEY_LENGTH_TEXT, SRT_KEY_LENGTH_TEXT, false )
>>>>>> >>> change_integer_list( srt_key_lengths, srt_key_length_names )
>>>>>> >>>
>>>>>> >>
>>>>>> >> --
>>>>>> >> Envoyé de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma brièveté.
>>>>>> >
>>>>>> > _______________________________________________
>>>>>> > vlc-devel mailing list
>>>>>> > To unsubscribe or modify your subscription options:
>>>>>> > https://mailman.videolan.org/listinfo/vlc-devel
>>>>>> _______________________________________________
>>>>>> vlc-devel mailing list
>>>>>> To unsubscribe or modify your subscription options:
>>>>>> https://mailman.videolan.org/listinfo/vlc-devel
>>>>> _______________________________________________
>>>>> vlc-devel mailing list
>>>>> To unsubscribe or modify your subscription options:
>>>>> https://mailman.videolan.org/listinfo/vlc-devel
>>>> 
>>>> _______________________________________________
>>>> vlc-devel mailing list
>>>> To unsubscribe or modify your subscription options:
>>>> https://mailman.videolan.org/listinfo/vlc-devel
>>> _______________________________________________
>>> vlc-devel mailing list
>>> To unsubscribe or modify your subscription options:
>>> https://mailman.videolan.org/listinfo/vlc-devel
>> 
>> _______________________________________________
>>  vlc-devel mailing list
>>  To unsubscribe or modify your subscription options:
>> https://mailman.videolan.org/listinfo/vlc-devel
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20190307/471f088f/attachment.html>


More information about the vlc-devel mailing list