diff --git a/client/DialConformance.h b/client/DialConformance.h index b6c4298..ae87919 100644 --- a/client/DialConformance.h +++ b/client/DialConformance.h @@ -157,21 +157,21 @@ private: */ void stop( string& responseHeaders ) - { stop(_stopurl, responseHeaders ); } + { stop(_name, responseHeaders ); } /** * Stop the application using a custom stop URL. * * @param[out] responseHeaders HTML response headers */ - void stop( string& stopurl, string& responseHeaders) + void stop( string& appName, string& responseHeaders) { - if( !stopurl.empty() ) + if( !appName.empty() ) { - _pServer->stopApplication( stopurl, responseHeaders ); + _pServer->stopApplication( appName, responseHeaders ); } #ifdef DEBUG - else ATRACE("%s: Not sending stop, stop URL is empty\n", __FUNCTION__); + else ATRACE("%s: Not sending stop, appName is empty\n", __FUNCTION__); #endif } diff --git a/client/DialServer.cpp b/client/DialServer.cpp index c22efff..2a27b63 100644 --- a/client/DialServer.cpp +++ b/client/DialServer.cpp @@ -263,7 +263,7 @@ int DialServer::hideApplication( getStatus( application, responseHeaders, responseBody ); int status = sendCommand( - (appUrl.append(application)).append("/"+m_stopEndPoint).append("/suspend"), + (appUrl.append(application)).append("/"+m_stopEndPoint).append("/hide"), COMMAND_HIDE, emptyPayload, responseHeaders, responseBody ); return status; } diff --git a/client/build.sh b/client/build.sh index b7e2c4f..e50577a 100755 --- a/client/build.sh +++ b/client/build.sh @@ -1,5 +1,5 @@ -TARGET=/usr/local/i686-netflix-linux-gnu-4.2/bin/i686-netflix-linux-gnu- \ -LDFLAGS="-L/usr/local/i686-netflix-linux-gnu-4.2/netflix/lib \ --Wl,-rpath,/usr/local/i686-netflix-linux-gnu-4.2/netflix/lib" \ -INCLUDES=-I/usr/local/i686-netflix-linux-gnu-4.2/netflix/include \ +TARGET=/usr/local/i686-netflix-linux-gnu-4.3/bin/i686-netflix-linux-gnu- \ +LDFLAGS="-L/usr/local/i686-netflix-linux-gnu-4.3/netflix/lib \ +-Wl,-rpath,/usr/local/i686-netflix-linux-gnu-4.3/netflix/lib" \ +INCLUDES=-I/usr/local/i686-netflix-linux-gnu-4.3/netflix/include \ make diff --git a/client/main.cpp b/client/main.cpp index ff6041b..481a23d 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -223,11 +223,11 @@ int handleUser(DialDiscovery *pDial) { printf("0. Rescan and list DIAL servers\n"); printf("1. Launch Netflix\n"); printf("2. Hide Netflix\n"); - printf("3. Kill Netflix\n"); + printf("3. Stop Netflix\n"); printf("4. Netflix status\n"); printf("5. Launch YouTube\n"); printf("6. Hide YouTube\n"); - printf("7. Kill YouTube\n"); + printf("7. Stop YouTube\n"); printf("8. YouTube status\n"); printf("9. Run conformance tests\n"); printf("10. Wake up on lan/wlan\n"); @@ -250,7 +250,7 @@ int handleUser(DialDiscovery *pDial) { pServer->hideApplication( netflix, responseHeaders, responseBody ); break; case 3: - printf("Kill Netflix\n"); + printf("Stop Netflix\n"); pServer->stopApplication( netflix, responseHeaders ); break; case 4: @@ -267,7 +267,7 @@ int handleUser(DialDiscovery *pDial) { pServer->hideApplication( youtube, responseHeaders, responseBody ); break; case 7: - printf("Kill YouTube\n"); + printf("Stop YouTube\n"); pServer->stopApplication( youtube, responseHeaders ); break; case 8: diff --git a/server/dial_server.c b/server/dial_server.c index 555c1f2..151f2bc 100644 --- a/server/dial_server.c +++ b/server/dial_server.c @@ -217,6 +217,18 @@ static void handle_app_status(struct mg_connection *conn, app->state = app->callbacks.status_cb(ds, app_name, app->run_id, &canStop, app->callback_data); + char dial_state_str[20]; + switch(app->state){ + case kDIALStatusHide: + strcpy (dial_state_str, "hidden"); + break; + case kDIALStatusRunning: + strcpy (dial_state_str, "running"); + break; + default: + strcpy (dial_state_str, "stopped"); + } + mg_printf( conn, "HTTP/1.1 200 OK\r\n" @@ -237,7 +249,7 @@ static void handle_app_status(struct mg_connection *conn, DIAL_VERSION, app->name, canStop ? "true" : "false", - app->state ? "running" : "stopped", + dial_state_str, app->state == kDIALStatusStopped ? "" : " \r\n", dial_data); @@ -261,7 +273,7 @@ static void handle_app_stop(struct mg_connection *conn, &canStop, app->callback_data); } - if (!app || app->state != kDIALStatusRunning) { + if (!app || app->state == kDIALStatusStopped) { mg_send_http_error(conn, 404, "Not Found", "Not Found"); } else { app->callbacks.stop_cb(ds, app_name, app->run_id, app->callback_data); @@ -449,7 +461,7 @@ static int is_allowed_origin(DIALServer* ds, char * origin, const char * app_nam #define APPS_URI "/apps/" #define RUN_URI "/run" -#define HIDE_URI "/suspend" +#define HIDE_URI "/hide" static void *options_response(DIALServer *ds, struct mg_connection *conn, char *host_header, char *origin_header, const char* app_name, const char* methods) { diff --git a/server/dial_server.h b/server/dial_server.h index 0804baf..f8f97c0 100644 --- a/server/dial_server.h +++ b/server/dial_server.h @@ -28,6 +28,13 @@ #include +//#define DEBUG +#ifdef DEBUG +#define ATRACE(...) printf(__VA_ARGS__) +#else +#define ATRACE(...) +#endif + /* * Dial application states */ @@ -40,7 +47,7 @@ typedef enum { /* * DIAL version that is reported via in the status response. */ -#define DIAL_VERSION ("\"2.0\"") +#define DIAL_VERSION ("\"2.1\"") /* * The maximum DIAL payload accepted per the DIAL 1.6.1 specification. diff --git a/server/jsmn.c b/server/jsmn.c new file mode 100644 index 0000000..e7765eb --- /dev/null +++ b/server/jsmn.c @@ -0,0 +1,311 @@ +#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 new file mode 100644 index 0000000..01ca99c --- /dev/null +++ b/server/jsmn.h @@ -0,0 +1,76 @@ +#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 802c48c..88e4198 100644 --- a/server/main.c +++ b/server/main.c @@ -40,6 +40,7 @@ #include #include +#include "url_lib.h" #include "nf_appmanager.h" #define NF_APP_MANAGER @@ -104,49 +105,6 @@ void signalHandler(int signal) } } -/* The URL encoding source code was obtained here: - * http://www.geekhideout.com/urlcode.shtml - */ - -/* Converts a hex character to its integer value */ -char from_hex(char ch) { - return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; -} - -/* Converts an integer value to its hex character*/ -char to_hex(char code) { - static char hex[] = "0123456789abcdef"; - return hex[code & 15]; -} - -/* Returns a url-encoded version of str */ -/* IMPORTANT: be sure to free() the returned string after use */ -char *url_encode(const char *str) { - const char *pstr; - char *buf, *pbuf; - pstr = str; - buf = malloc(strlen(str) * 3 + 1); - pbuf = buf; - if( buf ) - { - while (*pstr) { - if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') - *pbuf++ = *pstr; - else if (*pstr == ' ') - *pbuf++ = '+'; - else - *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15); - pstr++; - } - *pbuf = '\0'; - } - return buf; -} - -/* - * End of URL ENCODE source - */ - /* * This function will walk /proc and look for the application in * /proc//comm. and /proc//cmdline to find it's command (executable diff --git a/server/makefile b/server/makefile index 480c58d..cc553fe 100644 --- a/server/makefile +++ b/server/makefile @@ -3,7 +3,7 @@ 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 +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 HEADERS := $(wildcard *.h) %.c: $(HEADERS) @@ -14,7 +14,7 @@ HEADERS := $(wildcard *.h) all: dialserver test dialserver: $(OBJS) - $(CC) -Wall -Werror -g $(OBJS) -ldl -lpthread -o dialserver + $(CC) -Wall -Werror -g $(OBJS) -ldl -lpthread -lrt -o dialserver test: make -C tests diff --git a/server/mq_ipc.c b/server/mq_ipc.c new file mode 100644 index 0000000..487f17a --- /dev/null +++ b/server/mq_ipc.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include + +#include "mq_ipc.h" + +#define PMODE 0655 + +static mqd_t mClientServer=-1; +static mqd_t mServerClient=-1; + +int createMessageQ(const char* fd, int flags) +{ + struct mq_attr attr; + attr.mq_maxmsg = 10; + attr.mq_msgsize = 512; + + 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 new file mode 100644 index 0000000..2543bd6 --- /dev/null +++ b/server/mq_ipc.h @@ -0,0 +1,18 @@ +#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 index 1b622b8..c058a95 100644 --- a/server/nf_appmanager.c +++ b/server/nf_appmanager.c @@ -1,28 +1,247 @@ #include #include +#include #include "nf_appmanager.h" +#include "mq_ipc.h" +#include "jsmn.h" +#include "url_lib.h" +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> 4), *pbuf++ = to_hex(*pstr & 15); + pstr++; + } + *pbuf = '\0'; + } + return buf; +} + +/* + * End of URL ENCODE source + */ diff --git a/server/url_lib.h b/server/url_lib.h index 209dfb3..1a9f750 100644 --- a/server/url_lib.h +++ b/server/url_lib.h @@ -58,4 +58,8 @@ char *parse_app_name(const char *uri); */ DIALData *parse_params(char * query_string); +/* Returns a url-encoded version of str */ +/* IMPORTANT: be sure to free() the returned string after use */ +char *url_encode(const char *str); + #endif // URLLIB_H_