Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
a0022ad6
Commit
a0022ad6
authored
Dec 23, 2015
by
Thomas Guillem
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
services_discovery: add a service discovery for mDNS
parent
6c8a2eb2
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
461 additions
and
0 deletions
+461
-0
NEWS
NEWS
+1
-0
configure.ac
configure.ac
+6
-0
modules/MODULES_LIST
modules/MODULES_LIST
+1
-0
modules/services_discovery/Makefile.am
modules/services_discovery/Makefile.am
+8
-0
modules/services_discovery/microdns.c
modules/services_discovery/microdns.c
+445
-0
No files found.
NEWS
View file @
a0022ad6
...
@@ -140,6 +140,7 @@ Muxers:
...
@@ -140,6 +140,7 @@ Muxers:
Service Discovery:
Service Discovery:
* New NetBios service discovery using libdsm
* New NetBios service discovery using libdsm
* New mDNS services discovery using libmicrodns
* Rewrite of the UPnP service discovery
* Rewrite of the UPnP service discovery
Mac OS X Interface
Mac OS X Interface
...
...
configure.ac
View file @
a0022ad6
...
@@ -4028,6 +4028,12 @@ dnl UPnP Plugin (Intel SDK)
...
@@ -4028,6 +4028,12 @@ dnl UPnP Plugin (Intel SDK)
dnl
dnl
PKG_ENABLE_MODULES_VLC([UPNP], [upnp], [libupnp], [Intel UPNP SDK],[auto])
PKG_ENABLE_MODULES_VLC([UPNP], [upnp], [libupnp], [Intel UPNP SDK],[auto])
dnl
dnl mDNS using libmicrodns
dnl
PKG_ENABLE_MODULES_VLC([MICRODNS], [], [microdns], [mDNS services discovery], [auto])
EXTEND_HELP_STRING([Misc options:])
EXTEND_HELP_STRING([Misc options:])
dnl
dnl
...
...
modules/MODULES_LIST
View file @
a0022ad6
...
@@ -224,6 +224,7 @@ $Id$
...
@@ -224,6 +224,7 @@ $Id$
* mediacodec: Android Jelly Bean MediaCodec decoder module
* mediacodec: Android Jelly Bean MediaCodec decoder module
* mediadirs: Picture/Music/Video user directories as service discoveries
* mediadirs: Picture/Music/Video user directories as service discoveries
* mft: Media Foundation Transform audio/video decoder
* mft: Media Foundation Transform audio/video decoder
* microdns: mDNS services discovery
* minimal_macosx: a minimal Mac OS X GUI, using the FrameWork
* minimal_macosx: a minimal Mac OS X GUI, using the FrameWork
* mirror: mirror video filter
* mirror: mirror video filter
* mjpeg: a demuxer for multipart and concatenated JPEG data
* mjpeg: a demuxer for multipart and concatenated JPEG data
...
...
modules/services_discovery/Makefile.am
View file @
a0022ad6
...
@@ -68,3 +68,11 @@ libos2drive_plugin_la_SOURCES = services_discovery/os2drive.c
...
@@ -68,3 +68,11 @@ libos2drive_plugin_la_SOURCES = services_discovery/os2drive.c
if
HAVE_OS2
if
HAVE_OS2
sd_LTLIBRARIES
+=
libos2drive_plugin.la
sd_LTLIBRARIES
+=
libos2drive_plugin.la
endif
endif
libmicrodns_plugin_la_SOURCES
=
services_discovery/microdns.c
libmicrodns_plugin_la_CFLAGS
=
$(AM_CFLAGS)
$(MICRODNS_CFLAGS)
libmicrodns_plugin_la_LIBADD
=
$(SOCKET_LIBS)
$(MICRODNS_LIBS)
libmicrodns_plugin_la_LDFLAGS
=
$(AM_LDFLAGS)
-rpath
'
$(sddir)
'
sd_LTLIBRARIES
+=
$(LTLIBmicrodns)
EXTRA_LTLIBRARIES
+=
libmicrodns_plugin.la
modules/services_discovery/microdns.c
0 → 100644
View file @
a0022ad6
/*****************************************************************************
* microdns.c: mDNS services discovery module
*****************************************************************************
* Copyright © 2016 VLC authors, VideoLAN and VideoLabs
*
* Authors: Steve Lhomme <robux4@videolabs.io>
* Thomas Guillem <thomas@gllm.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_modules.h>
#include <vlc_services_discovery.h>
#include <microdns/microdns.h>
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
VLC_SD_PROBE_HELPER
(
"microdns"
,
"mDNS Network Discovery"
,
SD_CAT_LAN
)
#define NAMES_TEXT N_( "Service Names" )
#define NAMES_LONGTEXT N_( "List of names to look for, separated with ','" )
#define CFG_PREFIX "sd-microdns-"
#define LISTEN_INTERVAL INT64_C(20000000)
/* 20 seconds */
#define TIMEOUT (LISTEN_INTERVAL + INT64_C(5000000))
/* interval + 5 seconds */
/*
* Module descriptor
*/
vlc_module_begin
()
set_shortname
(
"mDNS"
)
set_description
(
N_
(
"mDNS Network Discovery"
)
)
set_category
(
CAT_PLAYLIST
)
set_subcategory
(
SUBCAT_PLAYLIST_SD
)
set_capability
(
"services_discovery"
,
0
)
set_callbacks
(
Open
,
Close
)
add_shortcut
(
"microdns"
)
add_string
(
CFG_PREFIX
"names"
,
NULL
,
NAMES_TEXT
,
NAMES_LONGTEXT
,
false
)
VLC_SD_PROBE_SUBMODULE
vlc_module_end
()
struct
services_discovery_sys_t
{
vlc_thread_t
thread
;
struct
mdns_ctx
*
p_microdns
;
char
*
psz_service_names_opt
;
const
char
**
ppsz_service_names
;
unsigned
int
i_nb_service_names
;
vlc_array_t
items
;
};
struct
item
{
char
*
psz_uri
;
input_item_t
*
p_input_item
;
mtime_t
i_last_seen
;
};
struct
srv
{
const
char
*
psz_protocol
;
char
*
psz_device_name
;
uint16_t
i_port
;
};
static
const
struct
{
const
char
*
psz_protocol
;
const
char
*
psz_service_name
;
uint16_t
i_default_port
;
}
protocols
[]
=
{
{
"ftp"
,
"_ftp._tcp.local"
,
21
},
{
"smb"
,
"_smb._tcp.local"
,
445
},
{
"nfs"
,
"_nfs._tcp.local"
,
2049
},
{
"sftp"
,
"_sftp-ssh._tcp.local"
,
22
},
};
#define NB_PROTOCOLS (sizeof(protocols) / sizeof(*protocols))
static
const
char
*
const
ppsz_options
[]
=
{
"names"
,
NULL
};
static
void
print_error
(
services_discovery_t
*
p_sd
,
const
char
*
psz_what
,
int
i_status
)
{
char
psz_err_str
[
128
];
if
(
mdns_strerror
(
i_status
,
psz_err_str
,
sizeof
(
psz_err_str
)
)
==
0
)
msg_Err
(
p_sd
,
"mDNS %s error: %s"
,
psz_what
,
psz_err_str
);
else
msg_Err
(
p_sd
,
"mDNS %s error: unknown: %d"
,
psz_what
,
i_status
);
}
static
int
strrcmp
(
const
char
*
s1
,
const
char
*
s2
)
{
size_t
m
,
n
;
m
=
strlen
(
s1
);
n
=
strlen
(
s2
);
if
(
n
>
m
)
return
1
;
return
strncmp
(
s1
+
m
-
n
,
s2
,
n
);
}
static
int
items_add
(
services_discovery_t
*
p_sd
,
char
*
psz_uri
,
input_item_t
*
p_input_item
)
{
services_discovery_sys_t
*
p_sys
=
p_sd
->
p_sys
;
struct
item
*
p_item
=
malloc
(
sizeof
(
struct
item
)
);
if
(
p_item
==
NULL
)
return
VLC_ENOMEM
;
p_item
->
psz_uri
=
psz_uri
;
p_item
->
p_input_item
=
p_input_item
;
p_item
->
i_last_seen
=
mdate
();
vlc_array_append
(
&
p_sys
->
items
,
p_item
);
services_discovery_AddItem
(
p_sd
,
p_input_item
,
NULL
);
return
VLC_SUCCESS
;
}
static
void
items_release
(
struct
item
*
p_item
)
{
input_item_Release
(
p_item
->
p_input_item
);
free
(
p_item
->
psz_uri
);
free
(
p_item
);
}
static
bool
items_exists
(
services_discovery_t
*
p_sd
,
const
char
*
psz_uri
)
{
services_discovery_sys_t
*
p_sys
=
p_sd
->
p_sys
;
for
(
int
i
=
0
;
i
<
vlc_array_count
(
&
p_sys
->
items
);
++
i
)
{
struct
item
*
p_item
=
vlc_array_item_at_index
(
&
p_sys
->
items
,
i
);
if
(
strcmp
(
psz_uri
,
p_item
->
psz_uri
)
==
0
)
{
p_item
->
i_last_seen
=
mdate
();
return
true
;
}
}
return
false
;
}
static
void
items_timeout
(
services_discovery_t
*
p_sd
)
{
services_discovery_sys_t
*
p_sys
=
p_sd
->
p_sys
;
mtime_t
i_now
=
mdate
();
/* Remove items that are not seen since TIMEOUT */
for
(
int
i
=
0
;
i
<
vlc_array_count
(
&
p_sys
->
items
);
++
i
)
{
struct
item
*
p_item
=
vlc_array_item_at_index
(
&
p_sys
->
items
,
i
);
if
(
i_now
-
p_item
->
i_last_seen
>
TIMEOUT
)
{
services_discovery_RemoveItem
(
p_sd
,
p_item
->
p_input_item
);
items_release
(
p_item
);
vlc_array_remove
(
&
p_sys
->
items
,
i
--
);
}
}
}
static
void
items_clear
(
services_discovery_t
*
p_sd
)
{
services_discovery_sys_t
*
p_sys
=
p_sd
->
p_sys
;
for
(
int
i
=
0
;
i
<
vlc_array_count
(
&
p_sys
->
items
);
++
i
)
{
struct
item
*
p_item
=
vlc_array_item_at_index
(
&
p_sys
->
items
,
i
);
items_release
(
p_item
);
}
vlc_array_clear
(
&
p_sys
->
items
);
}
static
void
new_entries_cb
(
void
*
p_this
,
int
i_status
,
const
struct
rr_entry
*
p_entries
)
{
services_discovery_t
*
p_sd
=
p_this
;
if
(
i_status
<
0
)
{
print_error
(
p_sd
,
"entry callback"
,
i_status
);
return
;
}
/* Count the number of servers */
unsigned
int
i_nb_srv
=
0
,
i_srv_idx
=
0
;
for
(
const
struct
rr_entry
*
p_entry
=
p_entries
;
p_entry
!=
NULL
;
p_entry
=
p_entry
->
next
)
{
if
(
p_entry
->
type
==
RR_SRV
)
i_nb_srv
++
;
}
if
(
i_nb_srv
==
0
)
return
;
struct
srv
*
p_srvs
=
calloc
(
i_nb_srv
,
sizeof
(
struct
srv
));
if
(
p_srvs
==
NULL
)
return
;
/* There is one ip for several srvs, fetch them */
const
char
*
psz_ip
=
NULL
;
for
(
const
struct
rr_entry
*
p_entry
=
p_entries
;
p_entry
!=
NULL
;
p_entry
=
p_entry
->
next
)
{
if
(
p_entry
->
type
==
RR_SRV
)
{
struct
srv
*
p_srv
=
&
p_srvs
[
i_srv_idx
];
for
(
unsigned
i
=
0
;
i
<
NB_PROTOCOLS
;
++
i
)
{
if
(
!
strrcmp
(
p_entry
->
name
,
protocols
[
i
].
psz_service_name
)
)
{
p_srv
->
psz_device_name
=
strndup
(
p_entry
->
name
,
strlen
(
p_entry
->
name
)
-
strlen
(
protocols
[
i
].
psz_service_name
)
-
1
);
if
(
p_srv
->
psz_device_name
==
NULL
)
break
;
p_srv
->
psz_protocol
=
protocols
[
i
].
psz_protocol
;
if
(
protocols
[
i
].
i_default_port
!=
p_entry
->
data
.
SRV
.
port
)
p_srv
->
i_port
=
p_entry
->
data
.
SRV
.
port
;
++
i_srv_idx
;
break
;
}
}
}
else
if
(
p_entry
->
type
==
RR_A
&&
psz_ip
==
NULL
)
psz_ip
=
p_entry
->
data
.
A
.
addr_str
;
/* TODO support ipv6
else if( p_entry->type == RR_AAAA )
psz_ip = p_entry->data.AAAA.addr_str;
*/
}
if
(
psz_ip
==
NULL
||
i_srv_idx
==
0
)
{
free
(
p_srvs
);
return
;
}
/* send new input items (if they don't already exist) */
for
(
i_srv_idx
=
0
;
i_srv_idx
<
i_nb_srv
;
++
i_srv_idx
)
{
struct
srv
*
p_srv
=
&
p_srvs
[
i_srv_idx
];
char
psz_port
[
7
];
/* ":65536\0" */
if
(
p_srv
->
i_port
!=
0
)
sprintf
(
psz_port
,
":%u"
,
p_srv
->
i_port
);
char
*
psz_uri
;
if
(
asprintf
(
&
psz_uri
,
"%s://%s%s"
,
p_srv
->
psz_protocol
,
psz_ip
,
p_srv
->
i_port
!=
0
?
psz_port
:
""
)
<
0
)
continue
;
if
(
items_exists
(
p_sd
,
psz_uri
)
)
{
free
(
psz_uri
);
continue
;
}
input_item_t
*
p_input_item
=
input_item_NewWithTypeExt
(
psz_uri
,
p_srv
->
psz_device_name
,
0
,
NULL
,
0
,
-
1
,
ITEM_TYPE_NODE
,
true
);
if
(
p_input_item
!=
NULL
&&
items_add
(
p_sd
,
psz_uri
,
p_input_item
)
!=
VLC_SUCCESS
)
{
if
(
p_input_item
!=
NULL
)
input_item_Release
(
p_input_item
);
free
(
psz_uri
);
}
}
for
(
i_srv_idx
=
0
;
i_srv_idx
<
i_nb_srv
;
++
i_srv_idx
)
free
(
p_srvs
[
i_srv_idx
].
psz_device_name
);
free
(
p_srvs
);
}
static
bool
stop_cb
(
void
*
p_this
)
{
services_discovery_t
*
p_sd
=
(
services_discovery_t
*
)
p_this
;
vlc_testcancel
();
items_timeout
(
p_sd
);
return
false
;
}
static
void
*
Run
(
void
*
p_this
)
{
services_discovery_t
*
p_sd
=
(
services_discovery_t
*
)
p_this
;
services_discovery_sys_t
*
p_sys
=
p_sd
->
p_sys
;
int
i_status
=
mdns_listen
(
p_sys
->
p_microdns
,
p_sys
->
ppsz_service_names
,
p_sys
->
i_nb_service_names
,
RR_PTR
,
LISTEN_INTERVAL
/
INT64_C
(
1000000
),
stop_cb
,
new_entries_cb
,
p_sd
);
if
(
i_status
<
0
)
print_error
(
p_sd
,
"listen"
,
i_status
);
return
NULL
;
}
static
int
Open
(
vlc_object_t
*
p_obj
)
{
services_discovery_t
*
p_sd
=
(
services_discovery_t
*
)
p_obj
;
services_discovery_sys_t
*
p_sys
=
NULL
;
int
i_ret
=
VLC_ENOMEM
;
p_sd
->
p_sys
=
p_sys
=
calloc
(
1
,
sizeof
(
services_discovery_sys_t
)
);
if
(
!
p_sys
)
return
VLC_ENOMEM
;
vlc_array_init
(
&
p_sys
->
items
);
config_ChainParse
(
p_sd
,
CFG_PREFIX
,
ppsz_options
,
p_sd
->
p_cfg
);
p_sys
->
psz_service_names_opt
=
var_GetNonEmptyString
(
p_sd
,
CFG_PREFIX
"names"
);
if
(
p_sys
->
psz_service_names_opt
)
{
/* Listen to protocols from names option */
unsigned
int
i_count
=
0
;
size_t
i_size
;
char
*
psz
=
p_sys
->
psz_service_names_opt
;
const
char
*
psz_end
=
psz
+
strlen
(
psz
);
while
(
psz
<
psz_end
&&
(
i_size
=
strcspn
(
psz
,
","
)
)
>
0
)
{
i_count
++
;
psz
+=
i_size
+
1
;
}
assert
(
i_count
>
0
);
p_sys
->
ppsz_service_names
=
calloc
(
i_count
,
sizeof
(
char
*
)
);
if
(
!
p_sys
->
ppsz_service_names
)
goto
error
;
psz
=
p_sys
->
psz_service_names_opt
;
for
(
unsigned
int
i
=
0
;
i
<
i_count
;
++
i
)
{
p_sys
->
ppsz_service_names
[
i
]
=
psz
;
i_size
=
strcspn
(
psz
,
","
);
assert
(
i_size
>
0
);
psz
[
i_size
]
=
'\0'
;
psz
+=
i_size
+
1
;
}
p_sys
->
i_nb_service_names
=
i_count
;
}
else
{
/* Listen to protocols that are handled by VLC */
const
unsigned
i_count
=
NB_PROTOCOLS
;
p_sys
->
ppsz_service_names
=
calloc
(
i_count
,
sizeof
(
char
*
)
);
if
(
!
p_sys
->
ppsz_service_names
)
goto
error
;
for
(
unsigned
int
i
=
0
;
i
<
i_count
;
++
i
)
{
/* Listen to a protocol only if a module can handle it */
if
(
module_exists
(
protocols
[
i
].
psz_protocol
)
)
p_sys
->
ppsz_service_names
[
p_sys
->
i_nb_service_names
++
]
=
protocols
[
i
].
psz_service_name
;
}
}
i_ret
=
VLC_EGENERIC
;
if
(
p_sys
->
i_nb_service_names
==
0
)
{
msg_Err
(
p_sd
,
"no services found"
);
goto
error
;
}
for
(
unsigned
int
i
=
0
;
i
<
p_sys
->
i_nb_service_names
;
++
i
)
msg_Dbg
(
p_sd
,
"mDNS: listening to %s"
,
p_sys
->
ppsz_service_names
[
i
]
);
int
i_status
;
if
(
(
i_status
=
mdns_init
(
&
p_sys
->
p_microdns
,
MDNS_ADDR_IPV4
,
MDNS_PORT
)
)
<
0
)
{
print_error
(
p_sd
,
"init"
,
i_status
);
goto
error
;
}
if
(
vlc_clone
(
&
p_sys
->
thread
,
Run
,
p_sd
,
VLC_THREAD_PRIORITY_LOW
)
)
{
msg_Err
(
p_sd
,
"Can't run the lookup thread"
);
goto
error
;
}
return
VLC_SUCCESS
;
error:
if
(
p_sys
->
p_microdns
!=
NULL
)
mdns_destroy
(
p_sys
->
p_microdns
);
free
(
p_sys
->
psz_service_names_opt
);
free
(
p_sys
->
ppsz_service_names
);
free
(
p_sys
);
return
i_ret
;
}
static
void
Close
(
vlc_object_t
*
p_this
)
{
services_discovery_t
*
p_sd
=
(
services_discovery_t
*
)
p_this
;
services_discovery_sys_t
*
p_sys
=
p_sd
->
p_sys
;
vlc_cancel
(
p_sys
->
thread
);
vlc_join
(
p_sys
->
thread
,
NULL
);
items_clear
(
p_sd
);
mdns_destroy
(
p_sys
->
p_microdns
);
free
(
p_sys
->
psz_service_names_opt
);
free
(
p_sys
->
ppsz_service_names
);
free
(
p_sys
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment