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_