Merge branch 'drops' into master
Change-Id: I2004b92321f50595f7e041d15ae2c0c593c1c0e3
diff --git a/src/server/dial_data.c b/src/server/dial_data.c
index 9587d1c..893d317 100644
--- a/src/server/dial_data.c
+++ b/src/server/dial_data.c
@@ -67,10 +67,8 @@
char value[256];
while (fscanf(f, "%255s %255s\n", key, value) != EOF) {
DIALData *newNode = (DIALData *) malloc(sizeof(DIALData));
- newNode->key = (char *) malloc(strlen(key));
- strcpy(newNode->key, key);
- newNode->value = (char *) malloc(strlen(value));
- strcpy(newNode->value, value);
+ newNode->key = strdup(key);
+ newNode->value = strdup(value);
newNode->next = result;
result = newNode;
}
diff --git a/src/server/dial_options.h b/src/server/dial_options.h
index 52bd052..5a3d306 100644
--- a/src/server/dial_options.h
+++ b/src/server/dial_options.h
@@ -26,14 +26,6 @@
#ifndef DIAL_OPTIONS_H
#define DIAL_OPTIONS_H
-#define DATA_PATH_OPTION "-D"
-#define DATA_PATH_OPTION_LONG "--data-path"
-#define DATA_PATH_DESCRIPTION "Path to netflix secure store"
-
-#define NETFLIX_PATH_OPTION "-N"
-#define NETFLIX_PATH_OPTION_LONG "--netflix-path"
-#define NETFLIX_PATH_DESCRIPTION "Path to Netflix application"
-
#define FRIENDLY_NAME_OPTION "-F"
#define FRIENDLY_NAME_OPTION_LONG "--friendly-name"
#define FRIENDLY_NAME_DESCRIPTION "Device Friendly Name"
@@ -46,6 +38,10 @@
#define UUID_OPTION_LONG "--uuid-name"
#define UUID_DESCRIPTION "UUID of the device"
+#define UI_TYPE_OPTION "-I"
+#define UI_TYPE_OPTION_LONG "--ui-type"
+#define UI_TYPE_DESCRIPTION "UI type"
+
struct dial_options
{
const char * pOption;
@@ -56,16 +52,6 @@
struct dial_options gDialOptions[] =
{
{
- DATA_PATH_OPTION,
- DATA_PATH_OPTION_LONG,
- DATA_PATH_DESCRIPTION
- },
- {
- NETFLIX_PATH_OPTION,
- NETFLIX_PATH_OPTION_LONG,
- NETFLIX_PATH_DESCRIPTION
- },
- {
FRIENDLY_NAME_OPTION,
FRIENDLY_NAME_OPTION_LONG,
FRIENDLY_NAME_DESCRIPTION,
@@ -79,6 +65,11 @@
UUID_OPTION,
UUID_OPTION_LONG,
UUID_DESCRIPTION
+ },
+ {
+ UI_TYPE_OPTION,
+ UI_TYPE_OPTION_LONG,
+ UI_TYPE_DESCRIPTION
}
};
diff --git a/src/server/dial_server.c b/src/server/dial_server.c
index 8cec387..61a0644 100644
--- a/src/server/dial_server.c
+++ b/src/server/dial_server.c
@@ -88,6 +88,23 @@
return ret;
}
+// Returns a pointer to the currently running app, or NULL if nothing is
+// running.
+static DIALApp **get_current_app(DIALServer *ds) {
+ DIALApp *app;
+ DIALApp **ret = &ds->apps;
+ int canStop;
+
+ for (app = ds->apps; app != NULL; ret = &app->next, app = app->next) {
+ app->state = app->callbacks.status_cb(ds, app->name, app->run_id,
+ &canStop, app->callback_data);
+ if (app->state == kDIALStatusRunning) {
+ break;
+ }
+ }
+ return ret;
+}
+
static void url_decode_xml_encode(char *dst, char *src, size_t src_size) {
char *url_decoded_key = (char *) malloc(src_size + 1);
urldecode(url_decoded_key, src, src_size);
@@ -118,7 +135,7 @@
const char *app_name,
const char *origin_header) {
char additional_data_param[256] = {0, };
- char body[DIAL_MAX_PAYLOAD + sizeof(additional_data_param) + 2] = {0, };
+ char body[DIAL_MAX_PAYLOAD] = {0, };
DIALApp *app;
DIALServer *ds = request_info->user_data;
int body_size;
@@ -143,15 +160,17 @@
in_port_t dial_port = DIAL_get_port(ds);
if (app->useAdditionalData) {
- if (body_size != 0) {
- strcat(body, "&");
- }
// Construct additionalDataUrl=http://host:port/apps/app_name/dial_data
- sprintf(additional_data_param,
- "additionalDataUrl=http%%3A%%2F%%2Flocalhost%%3A%d%%2Fapps%%2F%s%%2Fdial_data%%3F",
+ snprintf(additional_data_param, sizeof(additional_data_param),
+ "%sadditionalDataUrl=http%%3A%%2F%%2Flocalhost%%3A%d%%2Fapps%%2F%s%%2Fdial_data%%3F",
+ (body_size != 0) ? "&" : "",
dial_port, app_name);
- strcat(body, additional_data_param);
- body_size = strlen(body);
+ if ((body_size + strlen(additional_data_param)) < DIAL_MAX_PAYLOAD) {
+ strcat(body, additional_data_param);
+ body_size = strlen(body);
+ } else {
+ fprintf(stderr, "payload too small for additional data\n");
+ }
}
fprintf(stderr, "Starting the app with params %s\n", body);
app->state = app->callbacks.start_cb(ds, app_name, body, body_size,
@@ -168,7 +187,11 @@
laddr, dial_port, app_name, origin_header);
// copy the payload into the application struct
memset(app->payload, 0, DIAL_MAX_PAYLOAD);
- memcpy(app->payload, body, body_size);
+ if (body_size<=DIAL_MAX_PAYLOAD) {
+ memcpy(app->payload, body, body_size);
+ } else {
+ fprintf(stderr, "payload too small for body of %d bytes\n", body_size);
+ }
} else {
mg_send_http_error(conn, 503, "Service Unavailable",
"Service Unavailable");
@@ -187,6 +210,31 @@
DIALServer *ds = request_info->user_data;
ds_lock(ds);
+ if (strlen(app_name) == 0) {
+ app = *get_current_app(ds);
+ if (app == NULL) {
+ mg_printf(
+ conn,
+ "HTTP/1.1 204 No Content\r\n"
+ "Access-Control-Allow-Origin: %s\r\n"
+ "Content-Length: 0"
+ "\r\n",
+ origin_header);
+ } else {
+ mg_printf(
+ conn,
+ "HTTP/1.1 302 Found\r\n"
+ "Access-Control-Allow-Origin: %s\r\n"
+ "Location: %s%s\r\n"
+ "\r\n",
+ origin_header,
+ request_info->uri,
+ app->name);
+ }
+ ds_unlock(ds);
+ return;
+ }
+
app = *find_app(ds, app_name);
if (!app) {
mg_send_http_error(conn, 404, "Not Found", "Not Found");
@@ -231,18 +279,44 @@
" <options allowStop=\"%s\"/>\r\n"
" <state>%s</state>\r\n"
"%s"
- " <additionalData>\n"
- "%s"
- "\n </additionalData>\n"
- "</service>\r\n",
+ " <capabilities>websocket</capabilities>\r\n",
origin_header,
DIAL_VERSION,
app->name,
canStop ? "true" : "false",
app->state ? "running" : "stopped",
app->state == kDIALStatusStopped ?
- "" : " <link rel=\"run\" href=\"run\"/>\r\n",
+ "" : " <link rel=\"run\" href=\"run\"/>\r\n");
+ if (strlen(dial_data)>0) {
+ mg_printf(
+ conn,
+ " <additionalData>\r\n"
+ "%s"
+ "\r\n </additionalData>\r\n",
dial_data);
+ }
+ if (app->callbacks.service_data_cb != NULL) {
+ struct CastServiceData serviceData = app->callbacks.service_data_cb(ds, app_name, app->run_id, app->callback_data);
+ mg_printf(conn,
+ " <servicedata xmlns=\"urn:chrome.google.com:cast\">\r\n"
+ " <connectionSvcURL>http://%s:%d%s</connectionSvcURL>\r\n"
+ " <protocols>\r\n"
+ " <protocol>%s</protocol>\r\n"
+ " </protocols>\r\n"
+ " </servicedata>\r\n",
+ serviceData.connection_svc_host,
+ serviceData.connection_svc_port,
+ serviceData.connection_svc_path,
+ serviceData.protocol);
+ }
+ if (app->callbacks.activity_status_cb != NULL) {
+ struct CastActivityStatus activityStatus = app->callbacks.activity_status_cb(ds, app_name, app->run_id, app->callback_data);
+ mg_printf(conn,
+ " <activity-status xmlns=\"urn:chrome.google.com:cast\">\r\n"
+ " <description>%s</description>\r\n"
+ " </activity-status>\r\n", activityStatus.description);
+ }
+ mg_printf(conn, "</service>\r\n");
ds_unlock(ds);
}
@@ -330,6 +404,27 @@
ds_unlock(ds);
}
+// Add logic to test if we should drop DIAL requests
+#define SAGE_PROPERTIES_PATH "/rw/sage/SageClient.properties"
+#define DIAL_DISABLED_PROPERTY "allow_dial=false"
+
+int dial_allowed() {
+ char property[1024];
+ FILE *sageProperties;
+ if (!(sageProperties = fopen(SAGE_PROPERTIES_PATH,"r"))) {
+ return 1;
+ }
+ while (!feof(sageProperties)) {
+ fgets(property, sizeof(property), sageProperties);
+ if (strncmp(property, DIAL_DISABLED_PROPERTY, strlen(DIAL_DISABLED_PROPERTY))==0) {
+ fclose(sageProperties);
+ return 0;
+ }
+ }
+ fclose(sageProperties);
+ return 1;
+}
+
static int ends_with(const char *str, const char *suffix) {
if (!str || !suffix)
return 0;
@@ -450,6 +545,9 @@
}
fprintf(stderr, "Origin %s, Host: %s\n", origin_header, host_header);
if (event == MG_NEW_REQUEST) {
+ // If DIAL is disabled, drop the request
+ if (!dial_allowed())
+ return "done";
// URL ends with run
if (!strncmp(request_info->uri + strlen(request_info->uri) - 4, RUN_URI,
strlen(RUN_URI))) {
@@ -496,6 +594,8 @@
// get app status
} else if (!strcmp(request_info->request_method, "GET")) {
handle_app_status(conn, request_info, app_name, origin_header);
+ } else if (!strcmp(request_info->request_method, "DELETE")) {
+ handle_app_stop(conn, request_info, app_name, origin_header);
} else {
mg_send_http_error(conn, 501, "Not Implemented",
"Not Implemented");
diff --git a/src/server/dial_server.h b/src/server/dial_server.h
index 42721fb..32afef8 100644
--- a/src/server/dial_server.h
+++ b/src/server/dial_server.h
@@ -44,7 +44,25 @@
/*
* The maximum DIAL payload accepted per the DIAL 1.6.1 specification.
*/
-#define DIAL_MAX_PAYLOAD (4096)
+/* Increased size in 1.7 to allow 256 bytes of additional data */
+#define DIAL_MAX_PAYLOAD (4352)
+
+/*
+ * Cast service data
+ */
+struct CastServiceData {
+ const char *connection_svc_host;
+ int connection_svc_port;
+ const char *connection_svc_path;
+ const char *protocol;
+};
+
+/*
+ * Cast activity status
+ */
+struct CastActivityStatus {
+ const char *description;
+};
/*
* Opaque DIAL server handle
@@ -74,6 +92,17 @@
typedef DIALStatus (*DIAL_app_status_cb)(DIALServer *ds, const char *app_name,
DIAL_run_t run_id, int* pCanStop,
void *callback_data);
+/*
+ * Cast service data callback
+ */
+typedef struct CastServiceData (*CAST_app_service_data_cb)(DIALServer *ds, const char *app_name,
+ DIAL_run_t run_id, void *callback_data);
+
+/*
+ * Cast service data callback
+ */
+typedef struct CastActivityStatus (*CAST_app_activity_status_cb)(DIALServer *ds, const char *app_name,
+ DIAL_run_t run_id, void *callback_data);
/*
* DIAL callbacks
@@ -82,6 +111,8 @@
DIAL_app_start_cb start_cb;
DIAL_app_stop_cb stop_cb;
DIAL_app_status_cb status_cb;
+ CAST_app_service_data_cb service_data_cb;
+ CAST_app_activity_status_cb activity_status_cb;
};
/*
diff --git a/src/server/main.c b/src/server/main.c
index 51e1fba..875f9c3 100644
--- a/src/server/main.c
+++ b/src/server/main.c
@@ -41,32 +41,29 @@
#define BUFSIZE 256
-static char *spAppNetflix = "netflix"; // name of the netflix executable
-static char *spDefaultNetflix = "../../../src/platform/qt/netflix";
-static char *spDefaultData="../../../src/platform/qt/data";
-static char *spNfDataDir = "NF_DATA_DIR=";
-static char *defaultLaunchParam = "source_type=12";
-static char *spDefaultFriendlyName = "DIAL server sample";
-static char *spDefaultModelName = "NOT A VALID MODEL NAME";
-static char *spDefaultUuid = "deadbeef-dead-beef-dead-beefdeadbeef";
-static char spDataDir[BUFSIZE];
-static char spNetflix[BUFSIZE];
+static char *spDefaultFriendlyName = "Google Fiber TV Box";
+static char *spDefaultModelName = "GFHD100";
+static char *spDefaultUuid = "0";
static char spFriendlyName[BUFSIZE];
static char spModelName[BUFSIZE];
static char spUuid[BUFSIZE];
+static char spUiType[BUFSIZE];
static int gDialPort;
-static char *spAppYouTube = "chrome";
-static char *spAppYouTubeMatch = "chrome.*google-chrome-dial";
-static char *spAppYouTubeExecutable = "/opt/google/chrome/google-chrome";
-static char *spYouTubePS3UserAgent = "--user-agent="
- "Mozilla/5.0 (PS3; Leanback Shell) AppleWebKit/535.22 (KHTML, like Gecko) "
- "Chrome/19.0.1048.0 LeanbackShell/01.00.01.73 QA Safari/535.22 Sony PS3/ "
- "(PS3, , no, CH)";
+static char *spAppNetflix = "netflix"; // name of the netflix executable
+static char *defaultLaunchParam = "source_type=12";
+
+static char *spAppYouTube = "browser_shell";
+static char *spAppYouTubeMatch = "www.youtube.com/tv";
+
+static char *spAppFiberTV = "miniclient";
+static char *spAppFiberTVMatch = NULL;
// Adding 20 bytes for prepended source_type for Netflix
static char sQueryParam[DIAL_MAX_PAYLOAD+20];
+static const char *spIpAddress;
+
static int doesMatch( char* pzExp, char* pzStr)
{
regex_t exp;
@@ -194,23 +191,57 @@
closedir(proc_fd);
} else {
- printf("/proc failed to open\n");
+ fprintf(stderr, "/proc failed to open\n");
}
return 0;
}
+/* Running an application is done through the runminiclient script */
static pid_t runApplication( const char * const args[], DIAL_run_t *run_id ) {
+ const char * const script_args[] = {"/etc/init.d/S99miniclient", "restart", 0};
+
+ /* Write application information to /tmp/runapp */
+ FILE *runapp = fopen("/tmp/runapp.tmp","w");
+ if (!runapp) {
+ fprintf(stderr, "Couldn't open /tmp/runapp.tmp file\n");
+ return kDIALStatusStopped;
+ }
+ for(int i = 0; args[i]; ++i) {
+ int outputCharacters = fprintf(runapp, "%s ", args[i]);
+ if (outputCharacters<0) {
+ fprintf(stderr, "Error writing to /tmp/runapp.tmp file\n");
+ fclose(runapp);
+ return kDIALStatusStopped;
+ }
+ }
+ fsync(fileno(runapp));
+ fclose(runapp);
+ runapp=NULL;
+ if (rename("/tmp/runapp.tmp", "/tmp/runapp")) {
+ fprintf(stderr, "Error renaming /tmp/runapp.tmp file\n");
+ return kDIALStatusStopped;
+ }
+
+
pid_t pid = fork();
if (pid != -1) {
if (!pid) { // child
- putenv(spDataDir);
- printf("Execute:\n");
- for(int i = 0; args[i]; ++i) {
- printf(" %d) %s\n", i, args[i]);
+ // Close all descriptors except stdin,stdout,stderr
+ int fd, maxfd;
+ maxfd = sysconf(_SC_OPEN_MAX);
+ for (fd=3;fd<maxfd;fd++) {
+ close(fd);
}
- execv(*args, (char * const *) args);
+ execv(*script_args, (char * const *) script_args);
+ // It won't reach this unless there was an error
+ fprintf(stderr, "Error executing %s\n", *script_args);
+ exit(1);
} else {
*run_id = (void *)(long)pid; // parent PID
+ // Wait until the script S99miniclient is done before continuing
+ waitpid(pid, NULL, 0);
+ // TODO(jfthibert) Should we try to wait a few seconds until the actual
+ // program is started?
}
return kDIALStatusRunning;
} else {
@@ -234,15 +265,16 @@
static DIALStatus youtube_start(DIALServer *ds, const char *appname,
const char *args, size_t arglen,
DIAL_run_t *run_id, void *callback_data) {
- printf("\n\n ** LAUNCH YouTube ** with args %s\n\n", args);
+ fprintf(stderr, "** LAUNCH YouTube ** with args %s\n\n", args);
- char url[512] = {0,}, data[512] = {0,};
- sprintf( url, "https://www.youtube.com/tv?%s", args);
- sprintf( data, "--user-data-dir=%s/.config/google-chrome-dial", getenv("HOME") );
+ char url[512] = {0,};
+ int urlLength = snprintf( url, sizeof(url), "https://www.youtube.com/tv?%s", args);
+ if (urlLength>=sizeof(url)) {
+ fprintf(stderr, "Warning, YouTube URL was truncated (%d>=%d)\n", urlLength, sizeof(url));
+ }
- const char * const youtube_args[] = { spAppYouTubeExecutable,
- spYouTubePS3UserAgent,
- data, "--app", url, NULL
+ const char * const youtube_args[] = { "youtube",
+ url, NULL
};
runApplication( youtube_args, run_id );
@@ -258,7 +290,7 @@
static void youtube_stop(DIALServer *ds, const char *appname, DIAL_run_t run_id,
void *callback_data) {
- printf("\n\n ** KILL YouTube **\n\n");
+ fprintf(stderr, "** KILL YouTube **\n");
pid_t pid;
if ((pid = isAppRunning( spAppYouTube, spAppYouTubeMatch ))) {
kill(pid, SIGTERM);
@@ -292,7 +324,7 @@
}
}
- printf("appPid = %s, shouldRelaunch = %s queryParams = %s\n",
+ fprintf(stderr, "appPid = %s, shouldRelaunch = %s queryParams = %s\n",
appPid?"TRUE":"FALSE",
shouldRelaunchApp?"TRUE":"FALSE",
sQueryParam );
@@ -301,7 +333,7 @@
// never be relaunched
if( !appPid )
{
- const char * const netflix_args[] = {spNetflix, "-Q", sQueryParam, 0};
+ const char * const netflix_args[] = {"netflix", "-Q", sQueryParam, 0};
return runApplication( netflix_args, run_id );
}
else return kDIALStatusRunning;
@@ -309,10 +341,8 @@
static DIALStatus netflix_status(DIALServer *ds, const char *appname,
DIAL_run_t run_id, int* pCanStop, void *callback_data) {
- // Netflix application can stop
- *pCanStop = 1;
-
- waitpid((pid_t)(long)run_id, NULL, WNOHANG); // reap child
+ // Netflix application can't stop
+ *pCanStop = 0;
return isAppRunning( spAppNetflix, NULL ) ? kDIALStatusRunning : kDIALStatusStopped;
}
@@ -323,22 +353,77 @@
pid = isAppRunning( spAppNetflix, NULL );
if( pid )
{
- printf("Killing pid %d\n", pid);
+ fprintf(stderr, "Killing pid %d\n", pid);
kill((pid_t)pid, SIGTERM);
- waitpid((pid_t)pid, NULL, 0); // reap child
}
}
-void run_ssdp(int port, const char *pFriendlyName, const char * pModelName, const char *pUuid);
+static DIALStatus fibertv_start(DIALServer *ds, const char *appname,
+ const char *args, size_t arglen,
+ DIAL_run_t *run_id, void *callback_data) {
+ fprintf(stderr, "** LAUNCH FiberTV **\n");
+
+ const char * const miniclient_args[] = { "miniclient", NULL };
+ runApplication( miniclient_args, run_id );
+
+ return kDIALStatusRunning;
+}
+
+static DIALStatus fibertv_status(DIALServer *ds, const char *appname,
+ DIAL_run_t run_id, int *pCanStop, void *callback_data) {
+ // FiberTV can stop
+ *pCanStop = 1;
+ return isAppRunning( spAppFiberTV, spAppFiberTVMatch ) ? kDIALStatusRunning : kDIALStatusStopped;
+}
+
+static void fibertv_stop(DIALServer *ds, const char *appname, DIAL_run_t run_id,
+ void *callback_data) {
+ fprintf(stderr, "** KILL FiberTV **\n");
+ pid_t pid;
+ if ((pid = isAppRunning( spAppFiberTV, spAppFiberTVMatch ))) {
+ kill(pid, SIGTERM);
+ }
+}
+
+static DIALStatus basil_start(DIALServer *ds, const char *appname,
+ const char *args, size_t arglen,
+ DIAL_run_t *run_id, void *callback_data) {
+ fprintf(stderr, "** LAUNCH GoogleFiberTV **\n");
+ return kDIALStatusRunning; // Basil is always running
+}
+
+static DIALStatus basil_status(DIALServer *ds, const char *appname,
+ DIAL_run_t run_id, int *pCanStop, void *callback_data) {
+ *pCanStop = 0;
+ return kDIALStatusRunning; // Basil is always running
+}
+
+static struct CastServiceData basil_service_data(DIALServer *ds, const char *appname,
+ DIAL_run_t run_id, void *callback_data) {
+ struct CastServiceData serviceData;
+ serviceData.connection_svc_host = spIpAddress;
+ serviceData.connection_svc_port = 5153;
+ serviceData.connection_svc_path = "/connections";
+ serviceData.protocol = "marjoram";
+ return serviceData;
+}
+
+static void basil_stop(DIALServer *ds, const char *appname, DIAL_run_t run_id,
+ void *callback_data) {
+ fprintf(stderr, "** KILL GoogleFiberTV (ignored) **\n");
+ // Basil cannot be killed, but log the attempt
+}
+
+void run_ssdp(int port, const char *pFriendlyName, const char * pModelName, const char *pUuid, const char **ppIpAddress);
static void printUsage()
{
int i, numberOfOptions = sizeof(gDialOptions) / sizeof(dial_options_t);
- printf("usage: dialserver <options>\n");
- printf("options:\n");
+ fprintf(stderr, "usage: dialserver <options>\n");
+ fprintf(stderr, "options:\n");
for( i = 0; i < numberOfOptions; i++ )
{
- printf(" %s|%s [value]: %s\n",
+ fprintf(stderr, " %s|%s [value]: %s\n",
gDialOptions[i].pOption,
gDialOptions[i].pLongOption,
gDialOptions[i].pOptionDescription );
@@ -349,29 +434,30 @@
{
// Destination is always one of our static buffers with size BUFSIZE
memset( dest, 0, BUFSIZE );
- memcpy( dest, pSource, strlen(pSource) );
-}
-
-static void setDataDir(char *pData)
-{
- setValue( spNfDataDir, spDataDir );
- strcat(spDataDir, pData);
+ strncpy( dest, pSource, BUFSIZE-1 );
}
void runDial(void)
{
DIALServer *ds;
ds = DIAL_create();
- struct DIALAppCallbacks cb_nf = {netflix_start, netflix_stop, netflix_status};
- struct DIALAppCallbacks cb_yt = {youtube_start, youtube_stop, youtube_status};
+ struct DIALAppCallbacks cb_nf = {netflix_start, netflix_stop, netflix_status, NULL, NULL};
+ struct DIALAppCallbacks cb_yt = {youtube_start, youtube_stop, youtube_status, NULL, NULL};
+ struct DIALAppCallbacks cb_ft = {fibertv_start, fibertv_stop, fibertv_status, NULL, NULL};
+ struct DIALAppCallbacks cb_gf = {basil_start, basil_stop, basil_status, basil_service_data, NULL};
DIAL_register_app(ds, "Netflix", &cb_nf, NULL, 1, ".netflix.com");
DIAL_register_app(ds, "YouTube", &cb_yt, NULL, 1, ".youtube.com");
+ if (strcmp(spUiType, "oregano") == 0) {
+ DIAL_register_app(ds, "GoogleFiberTV", &cb_gf, NULL, 0, NULL);
+ } else {
+ DIAL_register_app(ds, "FiberTV", &cb_ft, NULL, 0, NULL);
+ }
DIAL_start(ds);
gDialPort = DIAL_get_port(ds);
- printf("launcher listening on gDialPort %d\n", gDialPort);
- run_ssdp(gDialPort, spFriendlyName, spModelName, spUuid);
+ fprintf(stderr, "launcher listening on gDialPort %d\n", gDialPort);
+ run_ssdp(gDialPort, spFriendlyName, spModelName, spUuid, &spIpAddress);
DIAL_stop(ds);
free(ds);
@@ -381,22 +467,18 @@
{
switch(index)
{
- case 0: // Data path
- memset( spDataDir, 0, sizeof(spDataDir) );
- setDataDir( pOption );
- break;
- case 1: // Netflix path
- setValue( pOption, spNetflix );
- break;
- case 2: // Friendly name
+ case 0: // Friendly name
setValue( pOption, spFriendlyName );
break;
- case 3: // Model Name
+ case 1: // Model Name
setValue( pOption, spModelName );
break;
- case 4: // UUID
+ case 2: // UUID
setValue( pOption, spUuid );
break;
+ case 3: // UI type
+ setValue( pOption, spUiType );
+ break;
default:
// Should not get here
fprintf( stderr, "Option %d not valid\n", index);
@@ -414,17 +496,21 @@
srand(time(NULL));
int i;
+
+ // Set stdout to unbuffered mode to avoid delayed logs
+ setvbuf(stdout, NULL, _IONBF, 0);
+
i = isAppRunning(spAppNetflix, NULL );
- printf("Netflix is %s\n", i ? "Running":"Not Running");
+ fprintf(stderr, "Netflix is %s\n", i ? "Running":"Not Running");
i = isAppRunning( spAppYouTube, spAppYouTubeMatch );
- printf("YouTube is %s\n", i ? "Running":"Not Running");
+ fprintf(stderr, "YouTube is %s\n", i ? "Running":"Not Running");
+ i = isAppRunning( spAppFiberTV, spAppFiberTVMatch );
+ fprintf(stderr, "FiberTV is %s\n", i ? "Running":"Not Running");
// set all defaults
setValue(spDefaultFriendlyName, spFriendlyName );
setValue(spDefaultModelName, spModelName );
setValue(spDefaultUuid, spUuid );
- setValue(spDefaultNetflix, spNetflix );
- setDataDir(spDefaultData);
// Process command line options
// Loop through pairs of command line options.
diff --git a/src/server/quick_ssdp.c b/src/server/quick_ssdp.c
index 2331a04..7c3a3ae 100644
--- a/src/server/quick_ssdp.c
+++ b/src/server/quick_ssdp.c
@@ -81,10 +81,14 @@
static char model_name[256];
static struct mg_context *ctx;
+extern int dial_allowed();
+
static void *request_handler(enum mg_event event,
struct mg_connection *conn,
const struct mg_request_info *request_info) {
if (event == MG_NEW_REQUEST) {
+ if (!dial_allowed())
+ return "done";
if (!strcmp(request_info->uri, "/dd.xml") &&
!strcmp(request_info->request_method, "GET")) {
mg_printf(conn, "HTTP/1.1 200 OK\r\n"
@@ -172,10 +176,11 @@
gBuf[bytes] = 0;
// sophisticated SSDP parsing algorithm
- if (!strstr(gBuf, "urn:dial-multiscreen-org:service:dial:1"))
+ if (!strstr(gBuf, "urn:dial-multiscreen-org:service:dial:1") &&
+ !strstr(gBuf, "ST: urn:dial-multiscreen-org:device:dial:1"))
{
#if 0 // use for debugging
- printf("Dropping: \n");
+ fprintf(stderr, "Dropping: \n");
{
int i;
for (i = 0; i < bytes; i++)
@@ -183,20 +188,22 @@
putchar(gBuf[i]);
}
}
- printf("\n##### End of DROP #######\n");
+ fprintf(stderr, "\n##### End of DROP #######\n");
#endif
continue;
}
- printf("Sending SSDP reply to %s:%d\n",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
- if (-1 == sendto(s, send_buf, send_size, 0, (struct sockaddr *)&saddr, addrlen)) {
- perror("sendto");
- continue;
+ if (dial_allowed()) {
+ fprintf(stderr, "Sending SSDP reply to %s:%d\n",
+ inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ if (-1 == sendto(s, send_buf, send_size, 0, (struct sockaddr *)&saddr, addrlen)) {
+ perror("sendto");
+ continue;
+ }
}
}
}
-void run_ssdp(int port, const char *pFriendlyName, const char * pModelName, const char *pUuid) {
+void run_ssdp(int port, const char *pFriendlyName, const char * pModelName, const char *pUuid, const char **ppIpAddress) {
struct sockaddr sa;
socklen_t len = sizeof(sa);
@@ -208,7 +215,7 @@
}
if(pModelName) {
strncpy(model_name, pModelName, sizeof(model_name));
- uuid[255] = '\0';
+ model_name[255] = '\0';
} else {
strcpy(model_name, "deadbeef-dead-beef-dead-beefdeadbeef");
}
@@ -221,12 +228,13 @@
dial_port = port;
get_local_address();
+ *ppIpAddress = ip_addr;
ctx = mg_start(&request_handler, NULL, SSDP_PORT);
if (mg_get_listen_addr(ctx, &sa, &len)) {
my_port = ntohs(((struct sockaddr_in *)&sa)->sin_port);
}
- printf("SSDP listening on %s:%d\n", ip_addr, my_port);
+ fprintf(stderr, "SSDP listening on %s:%d\n", ip_addr, my_port);
handle_mcast();
}