diff options
author | Thomas Bernard <bernard@users.sourceforge.net> | 2011-02-02 17:57:12 +0300 |
---|---|---|
committer | Carl Fürstenberg <azatoth@gmail.com> | 2011-03-29 03:00:08 +0400 |
commit | e3e794e6053436a58810f19f8f3cd9350f28277c (patch) | |
tree | 3155a71fa809f98de968ce5ed330a70716f873e0 | |
parent | eb024683b54aef0fd711a8edda80262ef01dc6b6 (diff) |
patch to use MiniSSDPd if availablepatch-bernard_minissdpd
with this patch, MiniDLNA uses MiniSSDPd to handle SSDP notify/discover/advertise processes.
It enable MiniDLNA and MiniUPnPd (and any other UPnP software supporting MiniSSDPd) to run on the same box.
-rw-r--r-- | codelength.h | 23 | ||||
-rw-r--r-- | minidlna.c | 9 | ||||
-rw-r--r-- | minissdp.c | 90 | ||||
-rw-r--r-- | minissdp.h | 5 | ||||
-rw-r--r-- | options.c | 3 | ||||
-rw-r--r-- | options.h | 3 | ||||
-rw-r--r-- | upnpglobalvars.c | 3 | ||||
-rw-r--r-- | upnpglobalvars.h | 2 |
8 files changed, 124 insertions, 14 deletions
diff --git a/codelength.h b/codelength.h new file mode 100644 index 0000000..8a5f495 --- /dev/null +++ b/codelength.h @@ -0,0 +1,23 @@ +/* $Id: codelength.h,v 1.1 2008/10/06 22:04:06 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas BERNARD + * copyright (c) 2005-2008 Thomas Bernard + * This software is subjet to the conditions detailed in the + * provided LICENCE file. */ +#ifndef __CODELENGTH_H__ +#define __CODELENGTH_H__ + +/* Encode length by using 7bit per Byte : + * Most significant bit of each byte specifies that the + * following byte is part of the code */ +#define DECODELENGTH(n, p) n = 0; \ + do { n = (n << 7) | (*p & 0x7f); } \ + while(*(p++)&0x80); + +#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ + if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ + if(n>=16384) *(p++) = (n >> 14) | 0x80; \ + if(n>=128) *(p++) = (n >> 7) | 0x80; \ + *(p++) = n & 0x7f; + +#endif @@ -547,6 +547,9 @@ init(int argc, char * * argv) if( (strcmp(ary_options[i].value, "yes") == 0) || atoi(ary_options[i].value) ) SETFLAG(DLNA_STRICT_MASK); break; + case UPNPMINISSDPDSOCKET: + minissdpdsocketpath = ary_options[i].value; + break; default: fprintf(stderr, "Unknown option in file %s\n", optionsfile); @@ -932,7 +935,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); @@ -2,7 +2,7 @@ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * - * Copyright (c) 2006, Thomas Bernard + * Copyright (c) 2006-2011, Thomas Bernard * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ #include <string.h> #include <unistd.h> #include <sys/socket.h> +#include <sys/un.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> @@ -44,14 +45,18 @@ #include "upnphttp.h" #include "upnpglobalvars.h" #include "minissdp.h" +#include "codelength.h" #include "log.h" /* SSDP ip/port */ #define SSDP_PORT (1900) #define SSDP_MCAST_ADDR ("239.255.255.250") +/* Prototypes */ +void ProcessSSDPData(int s, char *bufr, struct sockaddr_in sendername, int n, unsigned short port) ; + 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 */ @@ -69,6 +74,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() { @@ -231,9 +238,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 @@ -338,17 +345,12 @@ SendSSDPNotifies2(int * sockets, * process SSDP M-SEARCH requests and responds to them */ void ProcessSSDPRequest(int s, unsigned short port) -/*ProcessSSDPRequest(int s, struct lan_addr_s * lan_addr, int n_lan_addr, - unsigned short port)*/ { int n; char bufr[1500]; socklen_t len_r; struct sockaddr_in sendername; - int i, l; - int lan_addr_index = 0; - char * st = NULL, * mx = NULL, * man = NULL, * mx_end = NULL; - int st_len = 0, mx_len = 0, man_len = 0, mx_val = 0; + len_r = sizeof(struct sockaddr_in); n = recvfrom(s, bufr, sizeof(bufr), 0, @@ -358,6 +360,15 @@ ProcessSSDPRequest(int s, unsigned short port) DPRINTF(E_ERROR, L_SSDP, "recvfrom(udp): %s\n", strerror(errno)); return; } + ProcessSSDPData(s, bufr, sendername, n, port); + +} + +void ProcessSSDPData(int s, char *bufr, struct sockaddr_in sendername, int n, unsigned short port) { + int i, l; + int lan_addr_index = 0; + char * st = NULL, * mx = NULL, * man = NULL, * mx_end = NULL; + int st_len = 0, mx_len = 0, man_len = 0, mx_val = 0; if(memcmp(bufr, "NOTIFY", 6) == 0) { @@ -463,6 +474,7 @@ ProcessSSDPRequest(int s, unsigned short port) /* strlen("ssdp:all") == 8 */ if(st_len==8 && (0 == memcmp(st, "ssdp:all", 8))) { + DPRINTF(E_INFO, L_SSDP, "ssdp:all found"); for(i=0; known_service_types[i]; i++) { l = (int)strlen(known_service_types[i]); @@ -526,3 +538,61 @@ 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; +} @@ -1,7 +1,7 @@ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * - * Copyright (c) 2006-2007, Thomas Bernard + * Copyright (c) 2006-2011, Thomas Bernard * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -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 @@ -59,7 +59,8 @@ static const struct { { UPNPDBDIR, "db_dir" }, { UPNPLOGDIR, "log_dir" }, { ENABLE_TIVO, "enable_tivo" }, - { ENABLE_DLNA_STRICT, "strict_dlna" } + { ENABLE_DLNA_STRICT, "strict_dlna" }, + { UPNPMINISSDPDSOCKET, "minissdpdsocket"} }; int @@ -54,7 +54,8 @@ enum upnpconfigoptions { UPNPDBDIR, /* base directory to store the database and album art cache */ UPNPLOGDIR, /* base directory to store the log file */ ENABLE_TIVO, /* enable support for streaming images and music to TiVo */ - ENABLE_DLNA_STRICT /* strictly adhere to DLNA specs */ + ENABLE_DLNA_STRICT, /* strictly adhere to DLNA specs */ + UPNPMINISSDPDSOCKET /* minissdpdsocket */ }; /* readoptionsfile() diff --git a/upnpglobalvars.c b/upnpglobalvars.c index 0c71f42..b40e5f3 100644 --- a/upnpglobalvars.c +++ b/upnpglobalvars.c @@ -82,6 +82,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 fbb9dc3..4aa4cbf 100644 --- a/upnpglobalvars.h +++ b/upnpglobalvars.h @@ -192,6 +192,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[]; |