Skip to content

Commit

Permalink
Added more functions
Browse files Browse the repository at this point in the history
Change bug for optargs
Added support icon for ssdp
Modify help info
  • Loading branch information
Microfcorp authored Apr 11, 2024
1 parent c14b9b0 commit 395b6fd
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 38 deletions.
6 changes: 6 additions & 0 deletions src/ssdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@
# define LOCATION_PORT 8080
#endif
#define LOCATION_DESC "/description.xml"
#define LOCATION_ICON "/icon.png"

#define MIME_XML "text/xml"
#define MIME_PNG "image/png"

#define SSDP_ST_ALL "ssdp:all"

Expand Down Expand Up @@ -108,10 +112,12 @@ extern int log_level;
extern int log_opts;
extern char uuid[42];
extern char url[128];
extern char deviceType[64];
extern char fname[128];
extern char model[128];
extern char modelNumber[128];
extern char serialNumber[128];
extern char iconFile[256];
extern char mfrurl[128];
extern char mfrnm[128];
extern int ttl;
Expand Down
40 changes: 26 additions & 14 deletions src/ssdpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ int ttl = MC_TTL_DEFAULT;
char *cachefn = NULL;
char *ver = NULL;
char *os = NULL;
char deviceType[64] = "Basic";
char fname[128];
char model[128];
char modelNumber[128];
char serialNumber[128];
char iconFile[256];
#ifdef MANUFACTURER_URL
char mfrurl[128] = MANUFACTURER_URL;
#else
Expand Down Expand Up @@ -561,28 +563,31 @@ static void signal_init(void)

static int usage(int code)
{
printf("Usage: %s [-hnsvw] [-c FILE] [-D MODEL] [-N MODELN] [-S SERIAL] [-d URL] [-i SEC] [-l LEVEL] [-m NAME] [-M URL]\n"
printf("Usage: %s [-hnsvw] [-c FILE] [-D MODEL] [-N MODELN] [-S SERIAL] [-d URL] [-i SEC] [-I ICON] [-T DTYPE] [-l LEVEL] [-m NAME] [-M URL]\n"
" [-p URL] [-P FILE] [-r SEC] [-R NUM] [-t TTL] [-u UUID]\n"
" [IFACE [IFACE ...]]\n"
"\n"
" -c FILE Path to alternate ssdpd.cache to store and/or read the UUID\n"
" -d URL Override UPnP description.xml URL in announcements. The '%%s' in\n"
" the URL is replaced with the IP, e.g. https://%%s:1901/main.xml\n"
" SSDP Params:\n"
" -T DTYPE Override deviceType in the default description.xml\n"
" -D MODEL Override modelName in the default description.xml\n"
" -N MODELN Override modelNumber in the default description.xml\n"
" -S SERIAL Override serialNumber in the default description.xml\n"
" -f FNAME Override friendlyName in the default description.xml\n"
" -h This help text\n"
" -i SEC SSDP notify interval (30-900), default %d sec\n"
" -l LVL Set log level: none, err, notice (default), info, debug\n"
" -m NAME Override manufacturer in the default description.xml\n"
" -m NAME Override manufacturer in the default description.xml\n"
" -M URL Override manufacturerURL in the default description.xml\n"
" -I ICON Icon file (only png file, required 128x128px)\n"
" -p URL Override presentationURL (WebUI) in the default description.xml\n"
" The '%%s' is replaced with the IP address. Default: http://%%s/\n"
" -c FILE Path to alternate ssdpd.cache to store and/or read the UUID\n"
" -d URL Override UPnP description.xml URL in announcements. The '%%s' in\n"
" the URL is replaced with the IP, e.g. https://%%s:1901/main.xml\n"
" -h This help text\n"
" -i SEC SSDP notify interval (30-900), default %d sec\n"
" -l LVL Set log level: none, err, notice (default), info, debug\n"
" -n Run in foreground, do not daemonize by default\n"
" -r SEC Interface refresh interval (5-1800), default %d sec\n"
" -R NUM Initial retries, using 10 sec refresh interval, default 3 times\n"
" Note: unused on systems with netlink interface monitoring.\n"
" -p URL Override presentationURL (WebUI) in the default description.xml\n"
" The '%%s' is replaced with the IP address. Default: http://%%s/\n"
" -P FILE Override PID file location, absolute path required\n"
" -s Use syslog, default unless running in foreground, -n\n"
" -t TTL TTL for multicast frames, default 2, according to the UDA\n"
Expand Down Expand Up @@ -614,7 +619,7 @@ int main(int argc, char *argv[])
int nlmon = 0;
int c;

while ((c = getopt(argc, argv, "c:d:D:f:hi:l:m:M:np:P:r:R:st:u:vwN:S:")) != EOF) {
while ((c = getopt(argc, argv, "c:d:D:f:hi:l:m:M:np:P:r:R:st:u:vwN:S:I:T:")) != EOF) {
switch (c) {
case 'c':
cachefn = strdup(optarg);
Expand All @@ -627,13 +632,20 @@ int main(int argc, char *argv[])
case 'D':
strlcpy(model, optarg, sizeof(model));
break;


case 'T':
strlcpy(deviceType, optarg, sizeof(deviceType));
break;
case 'N':
strlcpy(modelNumber, optarg, sizeof(model));
strlcpy(modelNumber, optarg, sizeof(modelNumber));
break;

case 'S':
strlcpy(serialNumber, optarg, sizeof(model));
strlcpy(serialNumber, optarg, sizeof(serialNumber));
break;

case 'I':
strlcpy(iconFile, optarg, sizeof(iconFile));
break;

case 'f':
Expand Down
94 changes: 70 additions & 24 deletions src/web.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,31 +46,24 @@ const char *xml =
" <minor>0</minor>\r\n"
" </specVersion>\r\n"
" <device>\r\n"
" <deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>\r\n"
" <deviceType>urn:schemas-upnp-org:device:%s:1</deviceType>\r\n"
" <friendlyName>%s</friendlyName>\r\n"
" <manufacturer>%s</manufacturer>\r\n%s"
" <modelName>%s</modelName>\r\n"
" <modelNumber>%s</modelNumber>\r\n"
" <serialNumber>%s</serialNumber>"
" <UDN>%s</UDN>\r\n"
" <presentationURL>%s</presentationURL>\r\n"
" <iconList>"
" <icon>"
" <mimetype>image/png</mimetype>"
" <height>120</height>"
" <width>120</width>"
" <depth>24</depth>"
" <url>icon.png</url>"
" </icon>"
" </iconList>"
" </device>\r\n"
//"<iconList>"
//"<icon>"
//"<mimetype>image/png</mimetype>"
//"<height>48</height>"
//"<width>48</width>"
//"<depth>24</depth>"
//"<url>icon48.png</url>"
//"</icon>"
//"<icon>"
//"<mimetype>image/png</mimetype>"
//"<height>120</height>"
//"<width>120</width>"
//"<depth>24</depth>"
//"<url>icon120.png</url>"
//"</icon>"
//"</iconList>"
"</root>\r\n"
"\r\n";

Expand Down Expand Up @@ -142,6 +135,12 @@ static int validate_http(int sd, char *http)
return 0;
}

static int errorNotFound(int sd){
if (write(sd, "HTTP/1.1 404 Not Found\r\n", 24) < 0)
logit(LOG_WARNING, "Failed returning status 404 to client: %s", strerror(errno));
return -1;
}

static int respond(int sd, struct sockaddr_in *sin)
{
struct pollfd pfd = {
Expand All @@ -151,7 +150,7 @@ static int respond(int sd, struct sockaddr_in *sin)
const char *head = "HTTP/1.1 200 OK\r\n"
"Date: %s\r\n"
"Server: ssdp-responder/%s\r\n"
"Content-Type: text/xml\r\n"
"Content-Type: %s\r\n"
"Connection: close\r\n"
"\r\n";
char manufacturer_url[192] = "";
Expand Down Expand Up @@ -187,28 +186,75 @@ static int respond(int sd, struct sockaddr_in *sin)
if (validate_http(sd, reqline[2]))
return -1;

snprintf(mesg, sizeof(mesg), head, compose_time(), VERSION);
snprintf(mesg, sizeof(mesg), head, compose_time(), VERSION, MIME_XML);
if (send(sd, mesg, strlen(mesg), 0) < 0)
return -1;
} else if (strncmp(reqline[0], "GET", 4) == 0) {
if (validate_http(sd, reqline[2]))
return -1;

/* XXX: Add support for icon as well */
if (!reqline[1] || !strstr(reqline[1], LOCATION_DESC)) {
if (write(sd, "HTTP/1.1 404 Not Found\r\n", 24) < 0)
logit(LOG_WARNING, "Failed returning status 404 to client: %s", strerror(errno));
return -1;
if (!reqline[1] || (!strstr(reqline[1], LOCATION_DESC) && !strstr(reqline[1], LOCATION_ICON))) {
return errorNotFound(sd);
}

if(strstr(reqline[1], LOCATION_ICON)){
if(!strlen(iconFile)){
return errorNotFound(sd);
}

FILE *fp = fopen(iconFile, "r"); //open file
if(fp)
{
logit(LOG_DEBUG, "Sending Icon reply ...");
//Calculate file size
int64_t _file_size = 0;
fseek(fp, 0, SEEK_END);
_file_size = ftello(fp);

//malloc buffer for image
uint8_t *buffer = (uint8_t*)malloc(_file_size + 1);
if(buffer == NULL){
logit(LOG_WARNING, "Failed malloc()");
return errorNotFound(sd);
}
fseek(fp, 0, SEEK_SET); //move to start file

//Read image file in buffer
if(!fread(buffer, _file_size, 1, fp)){
logit(LOG_DEBUG, "Error reading image file");
return errorNotFound(sd);
}

snprintf(mesg, sizeof(mesg), head, compose_time(), VERSION, MIME_PNG); //Generate head string
//Send HTTP Headers
if (send(sd, mesg, strlen(mesg), 0) < 0) {
logit(LOG_WARNING, "Failed sending file to client: %s", strerror(errno));
}
//Send Image buffer
if (send(sd, buffer, _file_size, 0) < 0) {
logit(LOG_WARNING, "Failed sending file to client: %s", strerror(errno));
}
fclose(fp); //Close file
free(buffer); //Free buffer
}
else{
logit(LOG_DEBUG, "Icon file not found ...");
return errorNotFound(sd);
}
return 0;
}

if(!strlen(fname))
gethostname(fname, sizeof(fname));
if (mfrurl[0])
snprintf(manufacturer_url, sizeof(manufacturer_url),
" <manufacturerURL>%s</manufacturerURL>\r\n", mfrurl);

logit(LOG_DEBUG, "Sending XML reply ...");
rc = snprintf(mesg, sizeof(mesg), head, compose_time(), VERSION);
rc = snprintf(mesg, sizeof(mesg), head, compose_time(), VERSION, MIME_XML);
snprintf(&mesg[rc], sizeof(mesg) - rc, xml,
deviceType,
fname,
mfrnm,
manufacturer_url,
Expand Down

0 comments on commit 395b6fd

Please sign in to comment.