diff --git a/.gitignore b/.gitignore index cb029e8..e8b5f53 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ +*.so *.o client/dialclient server/dialserver server/tests/run_tests +client/report.html diff --git a/server/dial_options.h b/server/dial_options.h index 1a587c5..6f6b970 100644 --- a/server/dial_options.h +++ b/server/dial_options.h @@ -50,10 +50,6 @@ #define WAKE_OPTION_LONG "--wake-on-wifi-len" #define WAKE_DESCRIPTION "Enable wake on wifi/len. Value: on/off. Default (on)" -#define NFMANAGER_OPTION "-A" -#define NFMANAGER_OPTION_LONG "--netflix-app-manager" -#define NFMANAGER_DESCRIPTION "Enable interface to netflix app manager." - struct dial_options { const char * pOption; @@ -92,11 +88,6 @@ struct dial_options gDialOptions[] = WAKE_OPTION, WAKE_OPTION_LONG, WAKE_DESCRIPTION - }, - { - NFMANAGER_OPTION, - NFMANAGER_OPTION_LONG, - NFMANAGER_DESCRIPTION } }; diff --git a/server/jsmn.c b/server/jsmn.c deleted file mode 100644 index e7765eb..0000000 --- a/server/jsmn.c +++ /dev/null @@ -1,311 +0,0 @@ -#include "jsmn.h" - -/** - * Allocates a fresh unused token from the token pull. - */ -static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, - jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *tok; - if (parser->toknext >= num_tokens) { - return NULL; - } - tok = &tokens[parser->toknext++]; - tok->start = tok->end = -1; - tok->size = 0; -#ifdef JSMN_PARENT_LINKS - tok->parent = -1; -#endif - return tok; -} - -/** - * Fills token type and boundaries. - */ -static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, - int start, int end) { - token->type = type; - token->start = start; - token->end = end; - token->size = 0; -} - -/** - * Fills next available token with JSON primitive. - */ -static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - int start; - - start = parser->pos; - - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - switch (js[parser->pos]) { -#ifndef JSMN_STRICT - /* In strict mode primitive must be followed by "," or "}" or "]" */ - case ':': -#endif - case '\t' : case '\r' : case '\n' : case ' ' : - case ',' : case ']' : case '}' : - goto found; - } - if (js[parser->pos] < 32 || js[parser->pos] >= 127) { - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } -#ifdef JSMN_STRICT - /* In strict mode primitive must be followed by a comma/object/array */ - parser->pos = start; - return JSMN_ERROR_PART; -#endif - -found: - if (tokens == NULL) { - parser->pos--; - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - parser->pos--; - return 0; -} - -/** - * Fills next token with JSON string. - */ -static int jsmn_parse_string(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - - int start = parser->pos; - - parser->pos++; - - /* Skip starting quote */ - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c = js[parser->pos]; - - /* Quote: end of string */ - if (c == '\"') { - if (tokens == NULL) { - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - return 0; - } - - /* Backslash: Quoted symbol expected */ - if (c == '\\' && parser->pos + 1 < len) { - int i; - parser->pos++; - switch (js[parser->pos]) { - /* Allowed escaped symbols */ - case '\"': case '/' : case '\\' : case 'b' : - case 'f' : case 'r' : case 'n' : case 't' : - break; - /* Allows escaped symbol \uXXXX */ - case 'u': - parser->pos++; - for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { - /* If it isn't a hex character we have an error */ - if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ - (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ - (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ - parser->pos = start; - return JSMN_ERROR_INVAL; - } - parser->pos++; - } - parser->pos--; - break; - /* Unexpected symbol */ - default: - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } - } - parser->pos = start; - return JSMN_ERROR_PART; -} - -/** - * Parse JSON string and fill tokens. - */ -int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens) { - int r; - int i; - jsmntok_t *token; - int count = parser->toknext; - - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c; - jsmntype_t type; - - c = js[parser->pos]; - switch (c) { - case '{': case '[': - count++; - if (tokens == NULL) { - break; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) - return JSMN_ERROR_NOMEM; - if (parser->toksuper != -1) { - tokens[parser->toksuper].size++; -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - } - token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); - token->start = parser->pos; - parser->toksuper = parser->toknext - 1; - break; - case '}': case ']': - if (tokens == NULL) - break; - type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); -#ifdef JSMN_PARENT_LINKS - if (parser->toknext < 1) { - return JSMN_ERROR_INVAL; - } - token = &tokens[parser->toknext - 1]; - for (;;) { - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - token->end = parser->pos + 1; - parser->toksuper = token->parent; - break; - } - if (token->parent == -1) { - break; - } - token = &tokens[token->parent]; - } -#else - for (i = parser->toknext - 1; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - parser->toksuper = -1; - token->end = parser->pos + 1; - break; - } - } - /* Error if unmatched closing bracket */ - if (i == -1) return JSMN_ERROR_INVAL; - for (; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - parser->toksuper = i; - break; - } - } -#endif - break; - case '\"': - r = jsmn_parse_string(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; - case '\t' : case '\r' : case '\n' : case ' ': - break; - case ':': - parser->toksuper = parser->toknext - 1; - break; - case ',': - if (tokens != NULL && parser->toksuper != -1 && - tokens[parser->toksuper].type != JSMN_ARRAY && - tokens[parser->toksuper].type != JSMN_OBJECT) { -#ifdef JSMN_PARENT_LINKS - parser->toksuper = tokens[parser->toksuper].parent; -#else - for (i = parser->toknext - 1; i >= 0; i--) { - if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { - if (tokens[i].start != -1 && tokens[i].end == -1) { - parser->toksuper = i; - break; - } - } - } -#endif - } - break; -#ifdef JSMN_STRICT - /* In strict mode primitives are: numbers and booleans */ - case '-': case '0': case '1' : case '2': case '3' : case '4': - case '5': case '6': case '7' : case '8': case '9': - case 't': case 'f': case 'n' : - /* And they must not be keys of the object */ - if (tokens != NULL && parser->toksuper != -1) { - jsmntok_t *t = &tokens[parser->toksuper]; - if (t->type == JSMN_OBJECT || - (t->type == JSMN_STRING && t->size != 0)) { - return JSMN_ERROR_INVAL; - } - } -#else - /* In non-strict mode every unquoted value is a primitive */ - default: -#endif - r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; - -#ifdef JSMN_STRICT - /* Unexpected char in strict mode */ - default: - return JSMN_ERROR_INVAL; -#endif - } - } - - if (tokens != NULL) { - for (i = parser->toknext - 1; i >= 0; i--) { - /* Unmatched opened object or array */ - if (tokens[i].start != -1 && tokens[i].end == -1) { - return JSMN_ERROR_PART; - } - } - } - - return count; -} - -/** - * Creates a new parser based over a given buffer with an array of tokens - * available. - */ -void jsmn_init(jsmn_parser *parser) { - parser->pos = 0; - parser->toknext = 0; - parser->toksuper = -1; -} - diff --git a/server/jsmn.h b/server/jsmn.h deleted file mode 100644 index 01ca99c..0000000 --- a/server/jsmn.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef __JSMN_H_ -#define __JSMN_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * JSON type identifier. Basic types are: - * o Object - * o Array - * o String - * o Other primitive: number, boolean (true/false) or null - */ -typedef enum { - JSMN_UNDEFINED = 0, - JSMN_OBJECT = 1, - JSMN_ARRAY = 2, - JSMN_STRING = 3, - JSMN_PRIMITIVE = 4 -} jsmntype_t; - -enum jsmnerr { - /* Not enough tokens were provided */ - JSMN_ERROR_NOMEM = -1, - /* Invalid character inside JSON string */ - JSMN_ERROR_INVAL = -2, - /* The string is not a full JSON packet, more bytes expected */ - JSMN_ERROR_PART = -3 -}; - -/** - * JSON token description. - * @param type type (object, array, string etc.) - * @param start start position in JSON data string - * @param end end position in JSON data string - */ -typedef struct { - jsmntype_t type; - int start; - int end; - int size; -#ifdef JSMN_PARENT_LINKS - int parent; -#endif -} jsmntok_t; - -/** - * JSON parser. Contains an array of token blocks available. Also stores - * the string being parsed now and current position in that string - */ -typedef struct { - unsigned int pos; /* offset in the JSON string */ - unsigned int toknext; /* next token to allocate */ - int toksuper; /* superior token node, e.g parent object or array */ -} jsmn_parser; - -/** - * Create JSON parser over an array of tokens - */ -void jsmn_init(jsmn_parser *parser); - -/** - * Run JSON parser. It parses a JSON data string into and array of tokens, each describing - * a single JSON object. - */ -int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens); - -#ifdef __cplusplus -} -#endif - -#endif /* __JSMN_H_ */ diff --git a/server/main.c b/server/main.c index 7d0d44f..7712642 100644 --- a/server/main.c +++ b/server/main.c @@ -41,28 +41,25 @@ #include #include "url_lib.h" -#include "nf_appmanager.h" +#include "nf_callbacks.h" #define BUFSIZE 256 -static char *spAppNetflix = "netflix"; // name of the netflix executable +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]; +char spNetflix[BUFSIZE]; static char spFriendlyName[BUFSIZE]; static char spModelName[BUFSIZE]; static char spUuid[BUFSIZE]; extern bool wakeOnWifiLan; static int gDialPort; -static bool sUseNFAppManager=false; - static char *spAppYouTube = "chrome"; static char *spAppYouTubeMatch = "chrome.*google-chrome-dial"; static char *spAppYouTubeExecutable = "/opt/google/chrome/google-chrome"; @@ -71,10 +68,7 @@ static char *spYouTubePS3UserAgent = "--user-agent=" "Chrome/19.0.1048.0 LeanbackShell/01.00.01.73 QA Safari/535.22 Sony PS3/ " "(PS3, , no, CH)"; -// Adding 20 bytes for prepended source_type for Netflix -static char sQueryParam[DIAL_MAX_PAYLOAD+DIAL_MAX_ADDITIONALURL+40]; - -static int doesMatch( char* pzExp, char* pzStr) +int doesMatch( char* pzExp, char* pzStr) { regex_t exp; int ret; @@ -109,7 +103,7 @@ void signalHandler(int signal) * name) and command line (if needed). * Implementors can override this function with an equivalent. */ -static int isAppRunning( char *pzName, char *pzCommandPattern ) { +int isAppRunning( char *pzName, char *pzCommandPattern ) { DIR* proc_fd = opendir("/proc"); if( proc_fd != NULL ) { struct dirent* procEntry; @@ -163,7 +157,7 @@ static int isAppRunning( char *pzName, char *pzCommandPattern ) { return 0; } -static pid_t runApplication( const char * const args[], DIAL_run_t *run_id ) { +pid_t runApplication( const char * const args[], DIAL_run_t *run_id ) { pid_t pid = fork(); if (pid != -1) { if (!pid) { // child @@ -190,7 +184,7 @@ static pid_t runApplication( const char * const args[], DIAL_run_t *run_id ) { * If they match, return false * If they don't match, return true */ -static int shouldRelaunch( +int shouldRelaunch( DIALServer *pServer, const char *pAppName, const char *args ) @@ -244,79 +238,6 @@ static void youtube_stop(DIALServer *ds, const char *appname, DIAL_run_t run_id, } } -static DIALStatus netflix_start(DIALServer *ds, const char *appname, - const char *payload, const char *additionalDataUrl, - DIAL_run_t *run_id, void *callback_data) { - int shouldRelaunchApp = 0; - int appPid = 0; - - // only launch Netflix if it isn't running - appPid = isAppRunning( spAppNetflix, NULL ); - shouldRelaunchApp = shouldRelaunch( ds, appname, payload ); - - // construct the payload to determine if it has changed from the previous launch - memset( sQueryParam, 0, sizeof(sQueryParam) ); - strcat( sQueryParam, defaultLaunchParam ); - if(strlen(payload)) - { - char * pUrlEncodedParams; - pUrlEncodedParams = url_encode( payload ); - if( pUrlEncodedParams ) - { - strcat( sQueryParam, "&dial="); - strcat( sQueryParam, pUrlEncodedParams ); - free( pUrlEncodedParams ); - } - } - - if(strlen(additionalDataUrl)){ - strcat(sQueryParam, "&"); - strcat(sQueryParam, additionalDataUrl); - } - - printf("appPid = %s, shouldRelaunch = %s queryParams = %s\n", - appPid?"TRUE":"FALSE", - shouldRelaunchApp?"TRUE":"FALSE", - sQueryParam ); - - // if its not running, launch it. The Netflix application should - // never be relaunched - if( !appPid ) - { - const char * const netflix_args[] = {spNetflix, "-Q", sQueryParam, 0}; - return runApplication( netflix_args, run_id ); - } - else return kDIALStatusRunning; -} - -static DIALStatus netflix_hide(DIALServer *ds, const char *app_name, - DIAL_run_t *run_id, void *callback_data) -{ - return (isAppRunning( spAppNetflix, NULL )) ? kDIALStatusRunning : kDIALStatusStopped; -} - -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 - - return isAppRunning( spAppNetflix, NULL ) ? kDIALStatusRunning : kDIALStatusStopped; -} - -static void netflix_stop(DIALServer *ds, const char *appname, DIAL_run_t run_id, - void *callback_data) { - int pid; - pid = isAppRunning( spAppNetflix, NULL ); - if( pid ) - { - printf("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 void printUsage() @@ -351,17 +272,10 @@ void runDial(void) DIALServer *ds; ds = DIAL_create(); struct DIALAppCallbacks cb_nf; - if (sUseNFAppManager){ - cb_nf.start_cb = am_netflix_start; - cb_nf.hide_cb = am_netflix_hide; - cb_nf.stop_cb = am_netflix_stop; - cb_nf.status_cb = am_netflix_status; - }else{ - cb_nf.start_cb = netflix_start; - cb_nf.hide_cb = netflix_hide; - cb_nf.stop_cb = netflix_stop; - cb_nf.status_cb = netflix_status; - } + cb_nf.start_cb = netflix_start; + cb_nf.hide_cb = netflix_hide; + cb_nf.stop_cb = netflix_stop; + cb_nf.status_cb = netflix_status; struct DIALAppCallbacks cb_yt = {youtube_start, youtube_hide, youtube_stop, youtube_status}; DIAL_register_app(ds, "Netflix", &cb_nf, NULL, 1, ".netflix.com"); @@ -407,13 +321,6 @@ static void processOption( int index, char * pOption ) exit(1); } break; - case 6: - if (strcmp(pOption, "true")==0){ - sUseNFAppManager=true; - }else{ - sUseNFAppManager=false; - } - break; default: // Should not get here fprintf( stderr, "Option %d not valid\n", index); diff --git a/server/makefile b/server/makefile index cc553fe..c2a8c70 100644 --- a/server/makefile +++ b/server/makefile @@ -3,23 +3,27 @@ CC=$(TARGET)gcc .PHONY: clean .DEFAULT_GOAL=all -OBJS := main.o dial_server.o mongoose.o quick_ssdp.o url_lib.o dial_data.o LinuxInterfaces.o nf_appmanager.o mq_ipc.o jsmn.o +OBJS := main.o dial_server.o mongoose.o quick_ssdp.o url_lib.o dial_data.o LinuxInterfaces.o HEADERS := $(wildcard *.h) %.c: $(HEADERS) %.o: %.c $(HEADERS) - $(CC) -Wall -Werror -g -std=gnu99 $(CFLAGS) -c $*.c -o $*.o +# $(CC) -Wall -Werror -g -std=gnu99 $(CFLAGS) -c $*.c -o $*.o + $(CC) -Wall -g -std=gnu99 $(CFLAGS) -c $*.c -o $*.o all: dialserver test -dialserver: $(OBJS) - $(CC) -Wall -Werror -g $(OBJS) -ldl -lpthread -lrt -o dialserver +nf_callbacks_lib: nf_callbacks.o + $(CC) -Wall -Werror -g nf_callbacks.o -o libnfCallbacks.so --shared + +dialserver: nf_callbacks_lib $(OBJS) + $(CC) -Wall -Werror -Wl,-rpath,. -g $(OBJS) -ldl -lpthread -lrt -L. -lnfCallbacks -o dialserver test: make -C tests ./tests/run_tests clean: - rm -f *.o dialserver + rm -f *.o dialserver *.so make -C tests clean diff --git a/server/mq_ipc.c b/server/mq_ipc.c deleted file mode 100644 index 01b70ba..0000000 --- a/server/mq_ipc.c +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include -#include -#include -#include - -#include "mq_ipc.h" - -#define PMODE 0655 -#define IPC_MAX_MSG_SIZE 5*1024 // Account for 4kb DIAL payload -#define IPC_MAX_MSG_COUNT 1 - -static mqd_t mClientServer=-1; -static mqd_t mServerClient=-1; - -int createMessageQ(const char* fd, int flags) -{ - struct mq_attr attr; - attr.mq_maxmsg = IPC_MAX_MSG_SIZE; - attr.mq_msgsize = IPC_MAX_MSG_COUNT; - - mqd_t handle = mq_open(fd, flags, PMODE, &attr); - if (handle == -1) { - printf("Failed to open Q at %s: %s \n", fd, strerror(errno)); - return -1; - } - - return handle; -} - -int sendInternal(const char* payload, int timeoutInSec, bool block) -{ - if (mClientServer == -1) { - return -1; - } - - if (block) { - if (mq_send(mClientServer, payload, strlen(payload)+1, 0) == -1) { - printf("Failed to send message: %s \n", strerror(errno)); - return -1; - }else{ - printf("mq message sent.\n"); - } - } else { - struct timespec tm; - clock_gettime(CLOCK_REALTIME, &tm); - tm.tv_sec += timeoutInSec; - - if (mq_timedsend(mClientServer, payload, strlen(payload)+1, 0, &tm) == -1) { - printf("Failed to send message: %s \n", strerror(errno)); - return -1; - } - } - - return 0; -} - -int receiveInternal(char* buffer, int bufferSize, int timeoutInSec, bool block) -{ - /* mqd_t qFd = getMessageQ(fd); */ - - if (mServerClient == -1) { - return -1; - } - - if (block) { - if (mq_receive(mServerClient, buffer, bufferSize, 0) == -1) { - printf("Failed to receive message: %s \n", strerror(errno)); - return -1; - } - } else { - struct timespec tm; - clock_gettime(CLOCK_REALTIME, &tm); - tm.tv_sec += timeoutInSec; - - if (mq_timedreceive(mServerClient, buffer, bufferSize, 0, &tm) == -1) { - printf("Failed to receive message: %s \n", strerror(errno)); - return -1; - } - } - - return 0; -} - -//============== public APIs =================== - -int mq_ipc_connect(const char* clientServer, const char* serverClient) -{ - // Write-only to send message to server - mClientServer = createMessageQ(clientServer, O_WRONLY); - - // Read-only to receive messages from server. - mServerClient = createMessageQ(serverClient, O_RDONLY); - - if ((mServerClient == -1 ) || (mClientServer == -1)) { - printf(" failed to conncet to server \n"); - return -1; - }else{ - printf("mq connected.\n"); - } - - return 0; -} - -int mq_ipc_disconnect() -{ - mq_close(mClientServer); - mq_close(mServerClient); - return 0; -} - -int mq_ipc_send(const char* payload) -{ - return sendInternal(payload, 0, true); -} - -int mq_ipc_receive(char* buffer, int bufferSize) -{ - return receiveInternal(buffer, bufferSize, 0, true); -} - -int mq_ipc_send_timed(const char* payload, int timeoutInSec) -{ - return sendInternal(payload, timeoutInSec, false); -} - -int mq_ipc_receive_timed(char* buffer, int bufferSize, int timeoutInSec) -{ - return receiveInternal(buffer, bufferSize, timeoutInSec, false); -} - - diff --git a/server/mq_ipc.h b/server/mq_ipc.h deleted file mode 100644 index 2543bd6..0000000 --- a/server/mq_ipc.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _MQ_IPC_H_ -#define _MQ_IPC_H_ - -#include /* For O_* constants */ -#include /* For mode constants */ -#include -#include - -int mq_ipc_connect(const char* clientServer, const char* serverClient); -int mq_ipc_disconnect(); - -int mq_ipc_send(const char* payload); -int mq_ipc_receive(char* buffer, int bufferSize); - -int mq_ipc_send_timed(const char* payload, int timeoutInSec); -int mq_ipc_receive_timed(char* buffer, int bufferSize, int timeoutInSec); - -#endif diff --git a/server/nf_appmanager.c b/server/nf_appmanager.c deleted file mode 100644 index 7cc75c1..0000000 --- a/server/nf_appmanager.c +++ /dev/null @@ -1,250 +0,0 @@ -#include -#include -#include -#include "nf_appmanager.h" -#include "mq_ipc.h" -#include "jsmn.h" -#include "url_lib.h" - -#define IPC_BUF_SIZE 5*1024 // account for 4kb payload -#define IPC_TIMEOUT 2 - -static char *defaultLaunchParam = "source_type=12"; -static char * mq_send_ch = "/fromAppManager"; -static char * mq_receive_ch = "/toAppManager"; -static char * mq_tx_msg_base = " {\"args\":\"%s\",\"message\":%d}"; - -static int s_run_id = 0; - -typedef enum ControllerCommand { - //----------------------------------- - // Commands sent to AM - //----------------------------------- - CMD_CNT_START, // Launch the app - CMD_CNT_HIDE, // Suspend app - CMD_CNT_START_FROM_HIDE, // Resume app - CMD_CNT_STOP=6, // Terminate app nicely because the user killed Netflix. - CMD_CNT_GET_STATUS=8, // Provide status of the app -}ControllerCommand_t; - -typedef enum ControllerResp { - //----------------------------------- - // Resp sent from AM - //----------------------------------- - RESP_OK, - RESP_ERR, -}ControllerResp_t; - -typedef enum NetflixStatus { - //----------------------------------- - // Netflix status - //----------------------------------- - STATUS_NETFLIX_RUNNING, - STATUS_NETFLIX_HIDE1, - STATUS_NETFLIX_HIDE2, - STATUS_NETFLIX_STOPPED, -}NetflixStatus_t; - - -void errorMsg() -{ - printf("\nIn this mode, a matching application manager must be started and listen on the appropriate IPC.\n\n"); - exit(1); -} - -static int jsoneq(const char *json, jsmntok_t *tok, const char *s) { - if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && - strncmp(json + tok->start, s, tok->end - tok->start) == 0) { - return 0; - } - return -1; -} - -NetflixStatus_t parse_nf_state(char* json_str, jsmntok_t* tokens, int num_tokens) -{ - for (int i=0; i +#include +#include +#include +#include +#include +#include +#include +#include "dial_server.h" +#include "url_lib.h" + +extern char *spAppNetflix; +extern char spNetflix[]; +static char *defaultLaunchParam = "source_type=12"; + +// Adding 20 bytes for prepended source_type for Netflix +static char sQueryParam[DIAL_MAX_PAYLOAD+DIAL_MAX_ADDITIONALURL+40]; + +int isAppRunning( char *pzName, char *pzCommandPattern ); +int shouldRelaunch(DIALServer *pServer, const char *pAppName, const char *args ); +pid_t runApplication( const char * const args[], DIAL_run_t *run_id ); + +DIALStatus netflix_start(DIALServer *ds, const char *appname, + const char *payload, const char *additionalDataUrl, + DIAL_run_t *run_id, void *callback_data) { + int shouldRelaunchApp = 0; + int appPid = 0; + + // only launch Netflix if it isn't running + appPid = isAppRunning( spAppNetflix, NULL ); + shouldRelaunchApp = shouldRelaunch( ds, appname, payload ); + + // construct the payload to determine if it has changed from the previous launch + memset( sQueryParam, 0, sizeof(sQueryParam) ); + strcat( sQueryParam, defaultLaunchParam ); + if(strlen(payload)) + { + char * pUrlEncodedParams; + pUrlEncodedParams = url_encode( payload ); + if( pUrlEncodedParams ){ + strcat( sQueryParam, "&dial="); + strcat( sQueryParam, pUrlEncodedParams ); + free( pUrlEncodedParams ); + } + } + + if(strlen(additionalDataUrl)){ + strcat(sQueryParam, "&"); + strcat(sQueryParam, additionalDataUrl); + } + + printf("appPid = %s, shouldRelaunch = %s queryParams = %s\n", + appPid?"TRUE":"FALSE", + shouldRelaunchApp?"TRUE":"FALSE", + sQueryParam ); + + // if its not running, launch it. The Netflix application should + // never be relaunched + if( !appPid ){ + const char * const netflix_args[] = {spNetflix, "-Q", sQueryParam, 0}; + return runApplication( netflix_args, run_id ); + } + else return kDIALStatusRunning; +} + +DIALStatus netflix_hide(DIALServer *ds, const char *app_name, + DIAL_run_t *run_id, void *callback_data) +{ + return (isAppRunning( spAppNetflix, NULL )) ? kDIALStatusRunning : kDIALStatusStopped; +} + +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 + + return isAppRunning( spAppNetflix, NULL ) ? kDIALStatusRunning : kDIALStatusStopped; +} + +void netflix_stop(DIALServer *ds, const char *appname, DIAL_run_t run_id, + void *callback_data) { + int pid; + pid = isAppRunning( spAppNetflix, NULL ); + if( pid ){ + printf("Killing pid %d\n", pid); + kill((pid_t)pid, SIGTERM); + waitpid((pid_t)pid, NULL, 0); // reap child + } +} + + diff --git a/server/nf_appmanager.h b/server/nf_callbacks.h similarity index 84% rename from server/nf_appmanager.h rename to server/nf_callbacks.h index 0a2230d..3159046 100644 --- a/server/nf_appmanager.h +++ b/server/nf_callbacks.h @@ -23,23 +23,23 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _NF_APPMANAGER_H_ -#define _NF_APPMANAGER_H_ +#ifndef _NF_CALLBACKS_H +#define _NF_CALLBACKS_H #include "dial_server.h" -DIALStatus am_netflix_start(DIALServer *ds, const char *appname, +DIALStatus netflix_start(DIALServer *ds, const char *appname, const char *payload, const char *additionalDataUrl, DIAL_run_t *run_id, void *callback_data); -DIALStatus am_netflix_hide(DIALServer *ds, const char *app_name, +DIALStatus netflix_hide(DIALServer *ds, const char *app_name, DIAL_run_t *run_id, void *callback_data); -DIALStatus am_netflix_status(DIALServer *ds, const char *appname, +DIALStatus netflix_status(DIALServer *ds, const char *appname, DIAL_run_t run_id, int* pCanStop, void *callback_data); -void am_netflix_stop(DIALServer *ds, const char *appname, DIAL_run_t run_id, +void netflix_stop(DIALServer *ds, const char *appname, DIAL_run_t run_id, void *callback_data); #endif