diff --git a/minidlna.c b/minidlna.c index 1180074..6798ffc 100644 --- a/minidlna.c +++ b/minidlna.c @@ -588,6 +588,9 @@ init(int argc, char * * argv) break; } break; + case UPNPMINISSDPDSOCKET: + minissdpdsocketpath = ary_options[i].value; + break; default: fprintf(stderr, "Unknown option in file %s\n", optionsfile); @@ -974,7 +977,11 @@ main(int argc, char * * argv) sudp = OpenAndConfSSDPReceiveSocket(n_lan_addr, lan_addr); if(sudp < 0) { - DPRINTF(E_FATAL, L_GENERAL, "Failed to open socket for receiving SSDP. EXITING\n"); + DPRINTF(E_INFO, L_GENERAL, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd\n"); + if(SubmitServicesToMiniSSDPD(lan_addr[0].str, runtime_vars.port) < 0) { + DPRINTF(E_FATAL, L_GENERAL, "Failed to connect to MiniSSDPd. EXITING"); + return 1; + } } /* open socket for HTTP connections. Listen on the 1st LAN address */ shttpl = OpenAndConfHTTPSocket(runtime_vars.port); diff --git a/minidlna.conf b/minidlna.conf index da55668..377e9b2 100644 --- a/minidlna.conf +++ b/minidlna.conf @@ -49,6 +49,9 @@ notify_interval=900 serial=12345678 model_number=1 +# specify the path to the MiniSSDPd socket +#minissdpdsocket=/var/run/minissdpd.sock + # use different container as root of the tree # possible values: # + "." - use standard container (this is the default) diff --git a/minissdp.c b/minissdp.c index 165f778..b1a2527 100644 --- a/minissdp.c +++ b/minissdp.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,7 @@ #include "upnpreplyparse.h" #include "getifaddr.h" #include "minissdp.h" +#include "codelength.h" #include "utils.h" #include "log.h" @@ -52,7 +54,7 @@ #define SSDP_MCAST_ADDR ("239.255.255.250") static int -AddMulticastMembership(int s, in_addr_t ifaddr/*const char * ifaddr*/) +AddMulticastMembership(int s, in_addr_t ifaddr) { struct ip_mreq imr; /* Ip multicast membership */ @@ -70,6 +72,8 @@ AddMulticastMembership(int s, in_addr_t ifaddr/*const char * ifaddr*/) return 0; } +/* Open and configure the socket listening for + * SSDP udp packets sent on 239.255.255.250 port 1900 */ int OpenAndConfSSDPReceiveSocket() { @@ -242,9 +246,9 @@ SendSSDPAnnounce2(int s, struct sockaddr_in sockname, int st_no, { int l, n; char buf[512]; - /* TODO : + /* * follow guideline from document "UPnP Device Architecture 1.0" - * put in uppercase. + * uppercase is recommended. * DATE: is recommended * SERVER: OS/ver UPnP/1.0 minidlna/1.0 * - check what to put in the 'Cache-Control' header @@ -742,3 +746,62 @@ SendSSDPGoodbye(int * sockets, int n_sockets) } return 0; } + +/* SubmitServicesToMiniSSDPD() : + * register services offered by MiniUPnPd to a running instance of + * MiniSSDPd */ +int +SubmitServicesToMiniSSDPD(const char * host, unsigned short port) { + struct sockaddr_un addr; + int s; + unsigned char buffer[2048]; + char strbuf[256]; + unsigned char * p; + int i, l; + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if(s < 0) { + DPRINTF(E_ERROR, L_SSDP, "socket(unix): %s", strerror(errno)); + return -1; + } + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, minissdpdsocketpath, sizeof(addr.sun_path)); + if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) { + DPRINTF(E_ERROR, L_SSDP, "connect(\"%s\"): %s", + minissdpdsocketpath, strerror(errno)); + return -1; + } + for(i = 0; known_service_types[i]; i++) { + buffer[0] = 4; + p = buffer + 1; + l = (int)strlen(known_service_types[i]); + if(i > 0) + l++; + CODELENGTH(l, p); + memcpy(p, known_service_types[i], l); + if(i > 0) + p[l-1] = '1'; + p += l; + l = snprintf(strbuf, sizeof(strbuf), "%s::%s%s", + uuidvalue, known_service_types[i], (i==0)?"":"1"); + CODELENGTH(l, p); + memcpy(p, strbuf, l); + p += l; + l = (int)strlen(MINIDLNA_SERVER_STRING); + CODELENGTH(l, p); + memcpy(p, MINIDLNA_SERVER_STRING, l); + p += l; + l = snprintf(strbuf, sizeof(strbuf), "http://%s:%u" ROOTDESC_PATH, + host, (unsigned int)port); + CODELENGTH(l, p); + memcpy(p, strbuf, l); + p += l; + if(write(s, buffer, p - buffer) < 0) { + DPRINTF(E_ERROR, L_SSDP, "write(): %s", strerror(errno)); + return -1; + } + } + close(s); + return 0; +} + diff --git a/minissdp.h b/minissdp.h index 7f79130..bcc7ff4 100644 --- a/minissdp.h +++ b/minissdp.h @@ -62,5 +62,8 @@ ProcessSSDPRequest(int s, unsigned short port); int SendSSDPGoodbye(int * sockets, int n); +int +SubmitServicesToMiniSSDPD(const char * host, unsigned short port); + #endif diff --git a/options.c b/options.c index a283040..36f8289 100644 --- a/options.c +++ b/options.c @@ -58,6 +58,7 @@ static const struct { { UPNPINOTIFY, "inotify" }, { UPNPDBDIR, "db_dir" }, { UPNPLOGDIR, "log_dir" }, + { UPNPMINISSDPDSOCKET, "minissdpdsocket"}, { ENABLE_TIVO, "enable_tivo" }, { ENABLE_DLNA_STRICT, "strict_dlna" }, { ROOT_CONTAINER, "root_container" } diff --git a/options.h b/options.h index b208542..bce4070 100644 --- a/options.h +++ b/options.h @@ -51,6 +51,7 @@ enum upnpconfigoptions { UPNPINOTIFY, /* enable inotify on the media directories */ UPNPDBDIR, /* base directory to store the database and album art cache */ UPNPLOGDIR, /* base directory to store the log file */ + UPNPMINISSDPDSOCKET, /* minissdpdsocket */ ENABLE_TIVO, /* enable support for streaming images and music to TiVo */ ENABLE_DLNA_STRICT, /* strictly adhere to DLNA specs */ ROOT_CONTAINER /* root ObjectID (instead of "0") */ diff --git a/upnpglobalvars.c b/upnpglobalvars.c index d059daa..3fe5cf1 100644 --- a/upnpglobalvars.c +++ b/upnpglobalvars.c @@ -80,6 +80,9 @@ char presentationurl[PRESENTATIONURL_MAX_LEN]; int n_lan_addr = 0; struct lan_addr_s lan_addr[MAX_LAN_ADDR]; +/* Path of the Unix socket used to communicate with MiniSSDPd */ +const char * minissdpdsocketpath = "/var/run/minissdpd.sock"; + /* UPnP-A/V [DLNA] */ sqlite3 * db; char dlna_no_conv[] = "DLNA.ORG_OP=01;DLNA.ORG_CI=0"; diff --git a/upnpglobalvars.h b/upnpglobalvars.h index eaf4de2..34648be 100644 --- a/upnpglobalvars.h +++ b/upnpglobalvars.h @@ -211,6 +211,8 @@ extern char pnpx_hwid[]; extern int n_lan_addr; extern struct lan_addr_s lan_addr[]; +extern const char * minissdpdsocketpath; + /* UPnP-A/V [DLNA] */ extern sqlite3 *db; extern char dlna_no_conv[];