Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
3ee5093b
Commit
3ee5093b
authored
Feb 07, 2016
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lib/upnp: use C++ exceptions instead of class Error
parent
6e2ad686
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
143 additions
and
230 deletions
+143
-230
ContentDirectoryService.cxx
src/db/plugins/upnp/ContentDirectoryService.cxx
+16
-30
UpnpDatabasePlugin.cxx
src/db/plugins/upnp/UpnpDatabasePlugin.cxx
+28
-59
ClientInit.cxx
src/lib/upnp/ClientInit.cxx
+19
-25
ClientInit.hxx
src/lib/upnp/ClientInit.hxx
+2
-4
ContentDirectoryService.cxx
src/lib/upnp/ContentDirectoryService.cxx
+14
-23
ContentDirectoryService.hxx
src/lib/upnp/ContentDirectoryService.hxx
+3
-3
Discovery.cxx
src/lib/upnp/Discovery.cxx
+31
-50
Discovery.hxx
src/lib/upnp/Discovery.hxx
+5
-7
Init.cxx
src/lib/upnp/Init.cxx
+12
-16
Init.hxx
src/lib/upnp/Init.hxx
+2
-4
UpnpNeighborPlugin.cxx
src/neighbor/plugins/UpnpNeighborPlugin.cxx
+11
-9
No files found.
src/db/plugins/upnp/ContentDirectoryService.cxx
View file @
3ee5093b
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
#include "Directory.hxx"
#include "Directory.hxx"
#include "util/NumberParser.hxx"
#include "util/NumberParser.hxx"
#include "util/UriUtil.hxx"
#include "util/UriUtil.hxx"
#include "util/RuntimeError.hxx"
#include "util/Error.hxx"
#include "util/Error.hxx"
#include <stdio.h>
#include <stdio.h>
...
@@ -59,21 +60,16 @@ ContentDirectoryService::readDirSlice(UpnpClient_Handle hdl,
...
@@ -59,21 +60,16 @@ ContentDirectoryService::readDirSlice(UpnpClient_Handle hdl,
"SortCriteria"
,
""
,
"SortCriteria"
,
""
,
"StartingIndex"
,
ofbuf
,
"StartingIndex"
,
ofbuf
,
"RequestedCount"
,
cntbuf
);
"RequestedCount"
,
cntbuf
);
if
(
request
==
nullptr
)
{
if
(
request
==
nullptr
)
error
.
Set
(
upnp_domain
,
"UpnpMakeAction() failed"
);
throw
std
::
runtime_error
(
"UpnpMakeAction() failed"
);
return
false
;
}
IXML_Document
*
response
;
IXML_Document
*
response
;
int
code
=
UpnpSendAction
(
hdl
,
m_actionURL
.
c_str
(),
m_serviceType
.
c_str
(),
int
code
=
UpnpSendAction
(
hdl
,
m_actionURL
.
c_str
(),
m_serviceType
.
c_str
(),
0
/*devUDN*/
,
request
,
&
response
);
0
/*devUDN*/
,
request
,
&
response
);
ixmlDocument_free
(
request
);
ixmlDocument_free
(
request
);
if
(
code
!=
UPNP_E_SUCCESS
)
{
if
(
code
!=
UPNP_E_SUCCESS
)
error
.
Format
(
upnp_domain
,
code
,
throw
FormatRuntimeError
(
"UpnpSendAction() failed: %s"
,
"UpnpSendAction() failed: %s"
,
UpnpGetErrorMessage
(
code
));
UpnpGetErrorMessage
(
code
));
return
false
;
}
const
char
*
value
=
ixmlwrap
::
getFirstElementValue
(
response
,
"NumberReturned"
);
const
char
*
value
=
ixmlwrap
::
getFirstElementValue
(
response
,
"NumberReturned"
);
didreadp
=
value
!=
nullptr
didreadp
=
value
!=
nullptr
...
@@ -129,22 +125,17 @@ ContentDirectoryService::search(UpnpClient_Handle hdl,
...
@@ -129,22 +125,17 @@ ContentDirectoryService::search(UpnpClient_Handle hdl,
"SortCriteria"
,
""
,
"SortCriteria"
,
""
,
"StartingIndex"
,
ofbuf
,
"StartingIndex"
,
ofbuf
,
"RequestedCount"
,
"0"
);
// Setting a value here gets twonky into fits
"RequestedCount"
,
"0"
);
// Setting a value here gets twonky into fits
if
(
request
==
0
)
{
if
(
request
==
0
)
error
.
Set
(
upnp_domain
,
"UpnpMakeAction() failed"
);
throw
std
::
runtime_error
(
"UpnpMakeAction() failed"
);
return
false
;
}
IXML_Document
*
response
;
IXML_Document
*
response
;
auto
code
=
UpnpSendAction
(
hdl
,
m_actionURL
.
c_str
(),
auto
code
=
UpnpSendAction
(
hdl
,
m_actionURL
.
c_str
(),
m_serviceType
.
c_str
(),
m_serviceType
.
c_str
(),
0
/*devUDN*/
,
request
,
&
response
);
0
/*devUDN*/
,
request
,
&
response
);
ixmlDocument_free
(
request
);
ixmlDocument_free
(
request
);
if
(
code
!=
UPNP_E_SUCCESS
)
{
if
(
code
!=
UPNP_E_SUCCESS
)
error
.
Format
(
upnp_domain
,
code
,
throw
FormatRuntimeError
(
"UpnpSendAction() failed: %s"
,
"UpnpSendAction() failed: %s"
,
UpnpGetErrorMessage
(
code
));
UpnpGetErrorMessage
(
code
));
return
false
;
}
const
char
*
value
=
const
char
*
value
=
ixmlwrap
::
getFirstElementValue
(
response
,
"NumberReturned"
);
ixmlwrap
::
getFirstElementValue
(
response
,
"NumberReturned"
);
...
@@ -182,22 +173,17 @@ ContentDirectoryService::getMetadata(UpnpClient_Handle hdl,
...
@@ -182,22 +173,17 @@ ContentDirectoryService::getMetadata(UpnpClient_Handle hdl,
"SortCriteria"
,
""
,
"SortCriteria"
,
""
,
"StartingIndex"
,
"0"
,
"StartingIndex"
,
"0"
,
"RequestedCount"
,
"1"
);
"RequestedCount"
,
"1"
);
if
(
request
==
nullptr
)
{
if
(
request
==
nullptr
)
error
.
Set
(
upnp_domain
,
"UpnpMakeAction() failed"
);
throw
std
::
runtime_error
(
"UpnpMakeAction() failed"
);
return
false
;
}
IXML_Document
*
response
;
IXML_Document
*
response
;
auto
code
=
UpnpSendAction
(
hdl
,
m_actionURL
.
c_str
(),
auto
code
=
UpnpSendAction
(
hdl
,
m_actionURL
.
c_str
(),
m_serviceType
.
c_str
(),
m_serviceType
.
c_str
(),
0
/*devUDN*/
,
request
,
&
response
);
0
/*devUDN*/
,
request
,
&
response
);
ixmlDocument_free
(
request
);
ixmlDocument_free
(
request
);
if
(
code
!=
UPNP_E_SUCCESS
)
{
if
(
code
!=
UPNP_E_SUCCESS
)
error
.
Format
(
upnp_domain
,
code
,
throw
FormatRuntimeError
(
"UpnpSendAction() failed: %s"
,
"UpnpSendAction() failed: %s"
,
UpnpGetErrorMessage
(
code
));
UpnpGetErrorMessage
(
code
));
return
false
;
}
bool
success
=
ReadResultTag
(
dirbuf
,
response
,
error
);
bool
success
=
ReadResultTag
(
dirbuf
,
response
,
error
);
ixmlDocument_free
(
response
);
ixmlDocument_free
(
response
);
...
...
src/db/plugins/upnp/UpnpDatabasePlugin.cxx
View file @
3ee5093b
...
@@ -179,16 +179,17 @@ UpnpDatabase::Configure(const ConfigBlock &, Error &)
...
@@ -179,16 +179,17 @@ UpnpDatabase::Configure(const ConfigBlock &, Error &)
}
}
bool
bool
UpnpDatabase
::
Open
(
Error
&
error
)
UpnpDatabase
::
Open
(
gcc_unused
Error
&
error
)
{
{
if
(
!
UpnpClientGlobalInit
(
handle
,
error
))
UpnpClientGlobalInit
(
handle
);
return
false
;
discovery
=
new
UPnPDeviceDirectory
(
handle
);
discovery
=
new
UPnPDeviceDirectory
(
handle
);
if
(
!
discovery
->
Start
(
error
))
{
try
{
discovery
->
Start
();
}
catch
(...)
{
delete
discovery
;
delete
discovery
;
UpnpClientGlobalFinish
();
UpnpClientGlobalFinish
();
return
false
;
throw
;
}
}
return
true
;
return
true
;
...
@@ -216,15 +217,11 @@ const LightSong *
...
@@ -216,15 +217,11 @@ const LightSong *
UpnpDatabase
::
GetSong
(
const
char
*
uri
,
Error
&
error
)
const
UpnpDatabase
::
GetSong
(
const
char
*
uri
,
Error
&
error
)
const
{
{
auto
vpath
=
stringToTokens
(
uri
,
"/"
,
true
);
auto
vpath
=
stringToTokens
(
uri
,
"/"
,
true
);
if
(
vpath
.
size
()
<
2
)
{
if
(
vpath
.
size
()
<
2
)
error
.
Format
(
db_domain
,
(
int
)
DatabaseErrorCode
::
NOT_FOUND
,
throw
DatabaseError
(
DatabaseErrorCode
::
NOT_FOUND
,
"No such song: %s"
,
uri
);
"No such song"
);
return
nullptr
;
}
ContentDirectoryService
server
;
auto
server
=
discovery
->
GetServer
(
vpath
.
front
().
c_str
());
if
(
!
discovery
->
GetServer
(
vpath
.
front
().
c_str
(),
server
,
error
))
return
nullptr
;
vpath
.
pop_front
();
vpath
.
pop_front
();
...
@@ -276,10 +273,7 @@ UpnpDatabase::SearchSongs(const ContentDirectoryService &server,
...
@@ -276,10 +273,7 @@ UpnpDatabase::SearchSongs(const ContentDirectoryService &server,
if
(
selection
.
filter
==
nullptr
)
if
(
selection
.
filter
==
nullptr
)
return
true
;
return
true
;
std
::
list
<
std
::
string
>
searchcaps
;
const
auto
searchcaps
=
server
.
getSearchCapabilities
(
handle
);
if
(
!
server
.
getSearchCapabilities
(
handle
,
searchcaps
,
error
))
return
false
;
if
(
searchcaps
.
empty
())
if
(
searchcaps
.
empty
())
return
true
;
return
true
;
...
@@ -434,13 +428,10 @@ UpnpDatabase::ReadNode(const ContentDirectoryService &server,
...
@@ -434,13 +428,10 @@ UpnpDatabase::ReadNode(const ContentDirectoryService &server,
if
(
!
server
.
getMetadata
(
handle
,
objid
,
dirbuf
,
error
))
if
(
!
server
.
getMetadata
(
handle
,
objid
,
dirbuf
,
error
))
return
false
;
return
false
;
if
(
dirbuf
.
objects
.
size
()
==
1
)
{
if
(
dirbuf
.
objects
.
size
()
!=
1
)
dirent
=
std
::
move
(
dirbuf
.
objects
.
front
());
throw
std
::
runtime_error
(
"Bad resource"
);
}
else
{
error
.
Format
(
upnp_domain
,
"Bad resource"
);
return
false
;
}
dirent
=
std
::
move
(
dirbuf
.
objects
.
front
());
return
true
;
return
true
;
}
}
...
@@ -495,24 +486,18 @@ UpnpDatabase::Namei(const ContentDirectoryService &server,
...
@@ -495,24 +486,18 @@ UpnpDatabase::Namei(const ContentDirectoryService &server,
// Look for the name in the sub-container list
// Look for the name in the sub-container list
UPnPDirObject
*
child
=
dirbuf
.
FindObject
(
i
->
c_str
());
UPnPDirObject
*
child
=
dirbuf
.
FindObject
(
i
->
c_str
());
if
(
child
==
nullptr
)
{
if
(
child
==
nullptr
)
error
.
Format
(
db_domain
,
throw
DatabaseError
(
DatabaseErrorCode
::
NOT_FOUND
,
(
int
)
DatabaseErrorCode
::
NOT_FOUND
,
"No such object"
);
"No such object"
);
return
false
;
}
if
(
i
==
last
)
{
if
(
i
==
last
)
{
odirent
=
std
::
move
(
*
child
);
odirent
=
std
::
move
(
*
child
);
return
true
;
return
true
;
}
}
if
(
child
->
type
!=
UPnPDirObject
::
Type
::
CONTAINER
)
{
if
(
child
->
type
!=
UPnPDirObject
::
Type
::
CONTAINER
)
error
.
Format
(
db_domain
,
throw
DatabaseError
(
DatabaseErrorCode
::
NOT_FOUND
,
(
int
)
DatabaseErrorCode
::
NOT_FOUND
,
"Not a container"
);
"Not a container"
);
return
false
;
}
objid
=
std
::
move
(
child
->
id
);
objid
=
std
::
move
(
child
->
id
);
}
}
...
@@ -607,10 +592,8 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
...
@@ -607,10 +592,8 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
break
;
break
;
default
:
default
:
error
.
Format
(
db_domain
,
throw
DatabaseError
(
DatabaseErrorCode
::
NOT_FOUND
,
(
int
)
DatabaseErrorCode
::
NOT_FOUND
,
"Not found"
);
"Not found"
);
return
false
;
}
}
if
(
visit_song
)
{
if
(
visit_song
)
{
...
@@ -620,12 +603,9 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
...
@@ -620,12 +603,9 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
return
false
;
return
false
;
if
(
dirent
.
type
!=
UPnPDirObject
::
Type
::
ITEM
||
if
(
dirent
.
type
!=
UPnPDirObject
::
Type
::
ITEM
||
dirent
.
item_class
!=
UPnPDirObject
::
ItemClass
::
MUSIC
)
{
dirent
.
item_class
!=
UPnPDirObject
::
ItemClass
::
MUSIC
)
error
.
Format
(
db_domain
,
throw
DatabaseError
(
DatabaseErrorCode
::
NOT_FOUND
,
(
int
)
DatabaseErrorCode
::
NOT_FOUND
,
"Not found"
);
"Not found"
);
return
false
;
}
std
::
string
path
=
songPath
(
server
.
getFriendlyName
(),
std
::
string
path
=
songPath
(
server
.
getFriendlyName
(),
dirent
.
id
);
dirent
.
id
);
...
@@ -693,11 +673,7 @@ UpnpDatabase::Visit(const DatabaseSelection &selection,
...
@@ -693,11 +673,7 @@ UpnpDatabase::Visit(const DatabaseSelection &selection,
{
{
auto
vpath
=
stringToTokens
(
selection
.
uri
,
"/"
,
true
);
auto
vpath
=
stringToTokens
(
selection
.
uri
,
"/"
,
true
);
if
(
vpath
.
empty
())
{
if
(
vpath
.
empty
())
{
std
::
vector
<
ContentDirectoryService
>
servers
;
for
(
const
auto
&
server
:
discovery
->
GetDirectories
())
{
if
(
!
discovery
->
GetDirectories
(
servers
,
error
))
return
false
;
for
(
const
auto
&
server
:
servers
)
{
if
(
visit_directory
)
{
if
(
visit_directory
)
{
const
LightDirectory
d
(
server
.
getFriendlyName
(),
0
);
const
LightDirectory
d
(
server
.
getFriendlyName
(),
0
);
if
(
!
visit_directory
(
d
,
error
))
if
(
!
visit_directory
(
d
,
error
))
...
@@ -718,10 +694,7 @@ UpnpDatabase::Visit(const DatabaseSelection &selection,
...
@@ -718,10 +694,7 @@ UpnpDatabase::Visit(const DatabaseSelection &selection,
std
::
string
servername
(
std
::
move
(
vpath
.
front
()));
std
::
string
servername
(
std
::
move
(
vpath
.
front
()));
vpath
.
pop_front
();
vpath
.
pop_front
();
ContentDirectoryService
server
;
auto
server
=
discovery
->
GetServer
(
servername
.
c_str
());
if
(
!
discovery
->
GetServer
(
servername
.
c_str
(),
server
,
error
))
return
false
;
return
VisitServer
(
server
,
vpath
,
selection
,
return
VisitServer
(
server
,
vpath
,
selection
,
visit_directory
,
visit_song
,
visit_playlist
,
error
);
visit_directory
,
visit_song
,
visit_playlist
,
error
);
}
}
...
@@ -737,12 +710,8 @@ UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection,
...
@@ -737,12 +710,8 @@ UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection,
if
(
!
visit_tag
)
if
(
!
visit_tag
)
return
true
;
return
true
;
std
::
vector
<
ContentDirectoryService
>
servers
;
if
(
!
discovery
->
GetDirectories
(
servers
,
error
))
return
false
;
std
::
set
<
std
::
string
>
values
;
std
::
set
<
std
::
string
>
values
;
for
(
auto
&
server
:
servers
)
{
for
(
auto
&
server
:
discovery
->
GetDirectories
()
)
{
UPnPDirContent
dirbuf
;
UPnPDirContent
dirbuf
;
if
(
!
SearchSongs
(
server
,
rootid
,
selection
,
dirbuf
,
error
))
if
(
!
SearchSongs
(
server
,
rootid
,
selection
,
dirbuf
,
error
))
return
false
;
return
false
;
...
...
src/lib/upnp/ClientInit.cxx
View file @
3ee5093b
...
@@ -23,10 +23,12 @@
...
@@ -23,10 +23,12 @@
#include "Callback.hxx"
#include "Callback.hxx"
#include "Domain.hxx"
#include "Domain.hxx"
#include "thread/Mutex.hxx"
#include "thread/Mutex.hxx"
#include "util/Error.hxx"
#include "util/
Runtime
Error.hxx"
#include <upnp/upnptools.h>
#include <upnp/upnptools.h>
#include <assert.h>
static
Mutex
upnp_client_init_mutex
;
static
Mutex
upnp_client_init_mutex
;
static
unsigned
upnp_client_ref
;
static
unsigned
upnp_client_ref
;
static
UpnpClient_Handle
upnp_client_handle
;
static
UpnpClient_Handle
upnp_client_handle
;
...
@@ -44,40 +46,32 @@ UpnpClientCallback(Upnp_EventType et, void *evp, void *cookie)
...
@@ -44,40 +46,32 @@ UpnpClientCallback(Upnp_EventType et, void *evp, void *cookie)
return
callback
.
Invoke
(
et
,
evp
);
return
callback
.
Invoke
(
et
,
evp
);
}
}
static
bool
static
void
DoInit
(
Error
&
error
)
DoInit
()
{
{
auto
code
=
UpnpRegisterClient
(
UpnpClientCallback
,
nullptr
,
auto
code
=
UpnpRegisterClient
(
UpnpClientCallback
,
nullptr
,
&
upnp_client_handle
);
&
upnp_client_handle
);
if
(
code
!=
UPNP_E_SUCCESS
)
{
if
(
code
!=
UPNP_E_SUCCESS
)
error
.
Format
(
upnp_domain
,
code
,
throw
FormatRuntimeError
(
"UpnpRegisterClient() failed: %s"
,
"UpnpRegisterClient() failed: %s"
,
UpnpGetErrorMessage
(
code
));
UpnpGetErrorMessage
(
code
));
return
false
;
}
return
true
;
}
}
bool
void
UpnpClientGlobalInit
(
UpnpClient_Handle
&
handle
,
Error
&
error
)
UpnpClientGlobalInit
(
UpnpClient_Handle
&
handle
)
{
{
if
(
!
UpnpGlobalInit
(
error
))
UpnpGlobalInit
();
return
false
;
bool
success
;
try
{
{
const
ScopeLock
protect
(
upnp_client_init_mutex
);
const
ScopeLock
protect
(
upnp_client_init_mutex
);
success
=
upnp_client_ref
>
0
||
DoInit
(
error
);
if
(
upnp_client_ref
==
0
)
}
DoInit
();
}
catch
(...)
{
if
(
success
)
{
++
upnp_client_ref
;
handle
=
upnp_client_handle
;
}
else
UpnpGlobalFinish
();
UpnpGlobalFinish
();
throw
;
}
return
success
;
++
upnp_client_ref
;
handle
=
upnp_client_handle
;
}
}
void
void
...
...
src/lib/upnp/ClientInit.hxx
View file @
3ee5093b
...
@@ -24,10 +24,8 @@
...
@@ -24,10 +24,8 @@
#include <upnp/upnp.h>
#include <upnp/upnp.h>
class
Error
;
void
UpnpClientGlobalInit
(
UpnpClient_Handle
&
handle
);
bool
UpnpClientGlobalInit
(
UpnpClient_Handle
&
handle
,
Error
&
error
);
void
void
UpnpClientGlobalFinish
();
UpnpClientGlobalFinish
();
...
...
src/lib/upnp/ContentDirectoryService.cxx
View file @
3ee5093b
...
@@ -26,7 +26,7 @@
...
@@ -26,7 +26,7 @@
#include "Util.hxx"
#include "Util.hxx"
#include "Action.hxx"
#include "Action.hxx"
#include "util/UriUtil.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "util/
Runtime
Error.hxx"
ContentDirectoryService
::
ContentDirectoryService
(
const
UPnPDevice
&
device
,
ContentDirectoryService
::
ContentDirectoryService
(
const
UPnPDevice
&
device
,
const
UPnPService
&
service
)
const
UPnPService
&
service
)
...
@@ -50,43 +50,34 @@ ContentDirectoryService::~ContentDirectoryService()
...
@@ -50,43 +50,34 @@ ContentDirectoryService::~ContentDirectoryService()
/* this destructor exists here just so it won't get inlined */
/* this destructor exists here just so it won't get inlined */
}
}
bool
std
::
list
<
std
::
string
>
ContentDirectoryService
::
getSearchCapabilities
(
UpnpClient_Handle
hdl
,
ContentDirectoryService
::
getSearchCapabilities
(
UpnpClient_Handle
hdl
)
const
std
::
list
<
std
::
string
>
&
result
,
Error
&
error
)
const
{
{
assert
(
result
.
empty
());
UniqueIxmlDocument
request
(
UpnpMakeAction
(
"GetSearchCapabilities"
,
m_serviceType
.
c_str
(),
UniqueIxmlDocument
request
(
UpnpMakeAction
(
"GetSearchCapabilities"
,
m_serviceType
.
c_str
(),
0
,
0
,
nullptr
,
nullptr
));
nullptr
,
nullptr
));
if
(
!
request
)
{
if
(
!
request
)
error
.
Set
(
upnp_domain
,
"UpnpMakeAction() failed"
);
throw
std
::
runtime_error
(
"UpnpMakeAction() failed"
);
return
false
;
}
IXML_Document
*
_response
;
IXML_Document
*
_response
;
auto
code
=
UpnpSendAction
(
hdl
,
m_actionURL
.
c_str
(),
auto
code
=
UpnpSendAction
(
hdl
,
m_actionURL
.
c_str
(),
m_serviceType
.
c_str
(),
m_serviceType
.
c_str
(),
0
/*devUDN*/
,
request
.
get
(),
&
_response
);
0
/*devUDN*/
,
request
.
get
(),
&
_response
);
if
(
code
!=
UPNP_E_SUCCESS
)
{
if
(
code
!=
UPNP_E_SUCCESS
)
error
.
Format
(
upnp_domain
,
code
,
throw
FormatRuntimeError
(
"UpnpSendAction() failed: %s"
,
"UpnpSendAction() failed: %s"
,
UpnpGetErrorMessage
(
code
));
UpnpGetErrorMessage
(
code
));
return
false
;
}
UniqueIxmlDocument
response
(
_response
);
UniqueIxmlDocument
response
(
_response
);
std
::
list
<
std
::
string
>
result
;
const
char
*
s
=
ixmlwrap
::
getFirstElementValue
(
response
.
get
(),
const
char
*
s
=
ixmlwrap
::
getFirstElementValue
(
response
.
get
(),
"SearchCaps"
);
"SearchCaps"
);
if
(
s
==
nullptr
||
*
s
==
0
)
if
(
s
==
nullptr
||
*
s
==
0
)
return
true
;
return
result
;
if
(
!
csvToStrings
(
s
,
result
))
{
if
(
!
csvToStrings
(
s
,
result
))
error
.
Set
(
upnp_domain
,
"Bad response"
);
throw
std
::
runtime_error
(
"Bad response"
);
return
false
;
}
return
true
;
return
result
;
}
}
src/lib/upnp/ContentDirectoryService.hxx
View file @
3ee5093b
...
@@ -115,12 +115,12 @@ public:
...
@@ -115,12 +115,12 @@ public:
/** Retrieve search capabilities
/** Retrieve search capabilities
*
*
* Throws std::runtime_error on error.
*
* @param[out] result an empty vector: no search, or a single '*' element:
* @param[out] result an empty vector: no search, or a single '*' element:
* any tag can be used in a search, or a list of usable tag names.
* any tag can be used in a search, or a list of usable tag names.
*/
*/
bool
getSearchCapabilities
(
UpnpClient_Handle
handle
,
std
::
list
<
std
::
string
>
getSearchCapabilities
(
UpnpClient_Handle
handle
)
const
;
std
::
list
<
std
::
string
>
&
result
,
Error
&
error
)
const
;
gcc_pure
gcc_pure
std
::
string
GetURI
()
const
{
std
::
string
GetURI
()
const
{
...
...
src/lib/upnp/Discovery.cxx
View file @
3ee5093b
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#include "system/Clock.hxx"
#include "system/Clock.hxx"
#include "Log.hxx"
#include "Log.hxx"
#include "util/ScopeExit.hxx"
#include "util/ScopeExit.hxx"
#include "util/RuntimeError.hxx"
#include <upnp/upnptools.h>
#include <upnp/upnptools.h>
...
@@ -209,8 +210,8 @@ UPnPDeviceDirectory::Invoke(Upnp_EventType et, void *evp)
...
@@ -209,8 +210,8 @@ UPnPDeviceDirectory::Invoke(Upnp_EventType et, void *evp)
return
UPNP_E_SUCCESS
;
return
UPNP_E_SUCCESS
;
}
}
bool
void
UPnPDeviceDirectory
::
ExpireDevices
(
Error
&
error
)
UPnPDeviceDirectory
::
ExpireDevices
()
{
{
const
unsigned
now
=
MonotonicClockS
();
const
unsigned
now
=
MonotonicClockS
();
bool
didsomething
=
false
;
bool
didsomething
=
false
;
...
@@ -226,9 +227,7 @@ UPnPDeviceDirectory::ExpireDevices(Error &error)
...
@@ -226,9 +227,7 @@ UPnPDeviceDirectory::ExpireDevices(Error &error)
}
}
if
(
didsomething
)
if
(
didsomething
)
return
Search
(
error
);
Search
();
return
true
;
}
}
UPnPDeviceDirectory
::
UPnPDeviceDirectory
(
UpnpClient_Handle
_handle
,
UPnPDeviceDirectory
::
UPnPDeviceDirectory
(
UpnpClient_Handle
_handle
,
...
@@ -245,56 +244,45 @@ UPnPDeviceDirectory::~UPnPDeviceDirectory()
...
@@ -245,56 +244,45 @@ UPnPDeviceDirectory::~UPnPDeviceDirectory()
/* this destructor exists here just so it won't get inlined */
/* this destructor exists here just so it won't get inlined */
}
}
bool
void
UPnPDeviceDirectory
::
Start
(
Error
&
error
)
UPnPDeviceDirectory
::
Start
()
{
{
if
(
!
queue
.
start
(
1
,
Explore
,
this
))
{
if
(
!
queue
.
start
(
1
,
Explore
,
this
))
error
.
Set
(
upnp_domain
,
"Discover work queue start failed"
);
throw
std
::
runtime_error
(
"Discover work queue start failed"
);
return
false
;
}
return
Search
(
error
);
Search
(
);
}
}
bool
void
UPnPDeviceDirectory
::
Search
(
Error
&
error
)
UPnPDeviceDirectory
::
Search
()
{
{
const
unsigned
now
=
MonotonicClockS
();
const
unsigned
now
=
MonotonicClockS
();
if
(
now
-
last_search
<
10
)
if
(
now
-
last_search
<
10
)
return
true
;
return
;
last_search
=
now
;
last_search
=
now
;
// We search both for device and service just in case.
// We search both for device and service just in case.
int
code
=
UpnpSearchAsync
(
handle
,
search_timeout
,
int
code
=
UpnpSearchAsync
(
handle
,
search_timeout
,
ContentDirectorySType
,
GetUpnpCookie
());
ContentDirectorySType
,
GetUpnpCookie
());
if
(
code
!=
UPNP_E_SUCCESS
)
{
if
(
code
!=
UPNP_E_SUCCESS
)
error
.
Format
(
upnp_domain
,
code
,
throw
FormatRuntimeError
(
"UpnpSearchAsync() failed: %s"
,
"UpnpSearchAsync() failed: %s"
,
UpnpGetErrorMessage
(
code
));
UpnpGetErrorMessage
(
code
));
return
false
;
}
code
=
UpnpSearchAsync
(
handle
,
search_timeout
,
code
=
UpnpSearchAsync
(
handle
,
search_timeout
,
MediaServerDType
,
GetUpnpCookie
());
MediaServerDType
,
GetUpnpCookie
());
if
(
code
!=
UPNP_E_SUCCESS
)
{
if
(
code
!=
UPNP_E_SUCCESS
)
error
.
Format
(
upnp_domain
,
code
,
throw
FormatRuntimeError
(
"UpnpSearchAsync() failed: %s"
,
"UpnpSearchAsync() failed: %s"
,
UpnpGetErrorMessage
(
code
));
UpnpGetErrorMessage
(
code
));
return
false
;
}
return
true
;
}
}
bool
std
::
vector
<
ContentDirectoryService
>
UPnPDeviceDirectory
::
GetDirectories
(
std
::
vector
<
ContentDirectoryService
>
&
out
,
UPnPDeviceDirectory
::
GetDirectories
()
Error
&
error
)
{
{
const
ScopeLock
protect
(
mutex
);
const
ScopeLock
protect
(
mutex
);
if
(
!
ExpireDevices
(
error
))
ExpireDevices
();
return
false
;
std
::
vector
<
ContentDirectoryService
>
out
;
for
(
auto
dit
=
directories
.
begin
();
for
(
auto
dit
=
directories
.
begin
();
dit
!=
directories
.
end
();
dit
++
)
{
dit
!=
directories
.
end
();
dit
++
)
{
for
(
const
auto
&
service
:
dit
->
device
.
services
)
{
for
(
const
auto
&
service
:
dit
->
device
.
services
)
{
...
@@ -304,18 +292,15 @@ UPnPDeviceDirectory::GetDirectories(std::vector<ContentDirectoryService> &out,
...
@@ -304,18 +292,15 @@ UPnPDeviceDirectory::GetDirectories(std::vector<ContentDirectoryService> &out,
}
}
}
}
return
true
;
return
out
;
}
}
bool
ContentDirectoryService
UPnPDeviceDirectory
::
GetServer
(
const
char
*
friendly_name
,
UPnPDeviceDirectory
::
GetServer
(
const
char
*
friendly_name
)
ContentDirectoryService
&
server
,
Error
&
error
)
{
{
const
ScopeLock
protect
(
mutex
);
const
ScopeLock
protect
(
mutex
);
if
(
!
ExpireDevices
(
error
))
ExpireDevices
();
return
false
;
for
(
const
auto
&
i
:
directories
)
{
for
(
const
auto
&
i
:
directories
)
{
const
auto
&
device
=
i
.
device
;
const
auto
&
device
=
i
.
device
;
...
@@ -323,15 +308,11 @@ UPnPDeviceDirectory::GetServer(const char *friendly_name,
...
@@ -323,15 +308,11 @@ UPnPDeviceDirectory::GetServer(const char *friendly_name,
if
(
device
.
friendlyName
!=
friendly_name
)
if
(
device
.
friendlyName
!=
friendly_name
)
continue
;
continue
;
for
(
const
auto
&
service
:
device
.
services
)
{
for
(
const
auto
&
service
:
device
.
services
)
if
(
isCDService
(
service
.
serviceType
.
c_str
()))
{
if
(
isCDService
(
service
.
serviceType
.
c_str
()))
server
=
ContentDirectoryService
(
device
,
return
ContentDirectoryService
(
device
,
service
);
service
);
return
true
;
}
}
}
}
error
.
Set
(
upnp_domain
,
"Server not found"
);
throw
std
::
runtime_error
(
"Server not found"
);
return
false
;
}
}
src/lib/upnp/Discovery.hxx
View file @
3ee5093b
...
@@ -120,20 +120,18 @@ public:
...
@@ -120,20 +120,18 @@ public:
UPnPDeviceDirectory
(
const
UPnPDeviceDirectory
&
)
=
delete
;
UPnPDeviceDirectory
(
const
UPnPDeviceDirectory
&
)
=
delete
;
UPnPDeviceDirectory
&
operator
=
(
const
UPnPDeviceDirectory
&
)
=
delete
;
UPnPDeviceDirectory
&
operator
=
(
const
UPnPDeviceDirectory
&
)
=
delete
;
bool
Start
(
Error
&
error
);
void
Start
(
);
/** Retrieve the directory services currently seen on the network */
/** Retrieve the directory services currently seen on the network */
bool
GetDirectories
(
std
::
vector
<
ContentDirectoryService
>
&
,
Error
&
);
std
::
vector
<
ContentDirectoryService
>
GetDirectories
(
);
/**
/**
* Get server by friendly name.
* Get server by friendly name.
*/
*/
bool
GetServer
(
const
char
*
friendly_name
,
ContentDirectoryService
GetServer
(
const
char
*
friendly_name
);
ContentDirectoryService
&
server
,
Error
&
error
);
private
:
private
:
bool
Search
(
Error
&
error
);
void
Search
(
);
/**
/**
* Look at the devices and get rid of those which have not
* Look at the devices and get rid of those which have not
...
@@ -142,7 +140,7 @@ private:
...
@@ -142,7 +140,7 @@ private:
*
*
* Caller must lock #mutex.
* Caller must lock #mutex.
*/
*/
bool
ExpireDevices
(
Error
&
error
);
void
ExpireDevices
(
);
void
LockAdd
(
ContentDirectoryDescriptor
&&
d
);
void
LockAdd
(
ContentDirectoryDescriptor
&&
d
);
void
LockRemove
(
const
std
::
string
&
id
);
void
LockRemove
(
const
std
::
string
&
id
);
...
...
src/lib/upnp/Init.cxx
View file @
3ee5093b
...
@@ -21,44 +21,40 @@
...
@@ -21,44 +21,40 @@
#include "Init.hxx"
#include "Init.hxx"
#include "Domain.hxx"
#include "Domain.hxx"
#include "thread/Mutex.hxx"
#include "thread/Mutex.hxx"
#include "util/Error.hxx"
#include "util/
Runtime
Error.hxx"
#include <upnp/upnp.h>
#include <upnp/upnp.h>
#include <upnp/upnptools.h>
#include <upnp/upnptools.h>
#include <upnp/ixml.h>
#include <upnp/ixml.h>
#include <assert.h>
static
Mutex
upnp_init_mutex
;
static
Mutex
upnp_init_mutex
;
static
unsigned
upnp_ref
;
static
unsigned
upnp_ref
;
static
bool
static
void
DoInit
(
Error
&
error
)
DoInit
()
{
{
auto
code
=
UpnpInit
(
0
,
0
);
auto
code
=
UpnpInit
(
0
,
0
);
if
(
code
!=
UPNP_E_SUCCESS
)
{
if
(
code
!=
UPNP_E_SUCCESS
)
error
.
Format
(
upnp_domain
,
code
,
throw
FormatRuntimeError
(
"UpnpInit() failed: %s"
,
"UpnpInit() failed: %s"
,
UpnpGetErrorMessage
(
code
));
UpnpGetErrorMessage
(
code
));
return
false
;
}
UpnpSetMaxContentLength
(
2000
*
1024
);
UpnpSetMaxContentLength
(
2000
*
1024
);
// Servers sometimes make error (e.g.: minidlna returns bad utf-8)
// Servers sometimes make error (e.g.: minidlna returns bad utf-8)
ixmlRelaxParser
(
1
);
ixmlRelaxParser
(
1
);
return
true
;
}
}
bool
void
UpnpGlobalInit
(
Error
&
error
)
UpnpGlobalInit
()
{
{
const
ScopeLock
protect
(
upnp_init_mutex
);
const
ScopeLock
protect
(
upnp_init_mutex
);
if
(
upnp_ref
==
0
&&
!
DoInit
(
error
)
)
if
(
upnp_ref
==
0
)
return
false
;
DoInit
()
;
++
upnp_ref
;
++
upnp_ref
;
return
true
;
}
}
void
void
...
...
src/lib/upnp/Init.hxx
View file @
3ee5093b
...
@@ -22,10 +22,8 @@
...
@@ -22,10 +22,8 @@
#include "check.h"
#include "check.h"
class
Error
;
void
UpnpGlobalInit
();
bool
UpnpGlobalInit
(
Error
&
error
);
void
void
UpnpGlobalFinish
();
UpnpGlobalFinish
();
...
...
src/neighbor/plugins/UpnpNeighborPlugin.cxx
View file @
3ee5093b
...
@@ -70,17 +70,19 @@ private:
...
@@ -70,17 +70,19 @@ private:
};
};
bool
bool
UpnpNeighborExplorer
::
Open
(
Error
&
error
)
UpnpNeighborExplorer
::
Open
(
gcc_unused
Error
&
error
)
{
{
UpnpClient_Handle
handle
;
UpnpClient_Handle
handle
;
if
(
!
UpnpClientGlobalInit
(
handle
,
error
))
UpnpClientGlobalInit
(
handle
);
return
false
;
discovery
=
new
UPnPDeviceDirectory
(
handle
,
this
);
discovery
=
new
UPnPDeviceDirectory
(
handle
,
this
);
if
(
!
discovery
->
Start
(
error
))
{
try
{
discovery
->
Start
();
}
catch
(...)
{
delete
discovery
;
delete
discovery
;
UpnpClientGlobalFinish
();
UpnpClientGlobalFinish
();
return
false
;
throw
;
}
}
return
true
;
return
true
;
...
@@ -98,10 +100,10 @@ UpnpNeighborExplorer::GetList() const
...
@@ -98,10 +100,10 @@ UpnpNeighborExplorer::GetList() const
{
{
std
::
vector
<
ContentDirectoryService
>
tmp
;
std
::
vector
<
ContentDirectoryService
>
tmp
;
{
try
{
Error
error
;
tmp
=
discovery
->
GetDirectories
()
;
if
(
!
discovery
->
GetDirectories
(
tmp
,
error
))
}
catch
(
const
std
::
runtime_error
&
e
)
{
LogError
(
error
);
LogError
(
e
);
}
}
List
result
;
List
result
;
...
...
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