diff --git a/client/DialServer.cpp b/client/DialServer.cpp index d1def42..c22efff 100644 --- a/client/DialServer.cpp +++ b/client/DialServer.cpp @@ -31,8 +31,10 @@ using namespace std; enum DIAL_COMMAND{ COMMAND_LAUNCH, COMMAND_STATUS, - COMMAND_KILL + COMMAND_KILL, + COMMAND_HIDE }; +const char* DIAL_COMMAND_STR[] = {"LAUNCH", "STATUS", "KILL", "HIDE"}; static size_t header_cb(void* ptr, size_t size, size_t nmemb, void* userdata) { @@ -78,7 +80,7 @@ int DialServer::sendCommand( return 0; } - if (command == COMMAND_LAUNCH) + if (command == COMMAND_LAUNCH || command == COMMAND_HIDE) { curl_easy_setopt(curl, CURLOPT_POST, true); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, payload.size()); @@ -94,10 +96,7 @@ int DialServer::sendCommand( { curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); } - ATRACE("Sending %s:%s\n", - command == COMMAND_LAUNCH ? "LAUNCH" : - (command == COMMAND_KILL ? "KILL" : "STATUS"), - url.c_str()); + ATRACE("Sending %s:%s\n", DIAL_COMMAND_STR[command], url.c_str()); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_cb); @@ -251,6 +250,24 @@ int DialServer::stopApplication( return status; } +int DialServer::hideApplication( + string &application, + string &responseHeaders, + string &responseBody ) +{ + ATRACE("%s: Hide %s\n", __FUNCTION__, application.c_str()); + string emptyPayload; + string appUrl = m_appsUrl; + + // just call status to update the run endpoint + getStatus( application, responseHeaders, responseBody ); + + int status = sendCommand( + (appUrl.append(application)).append("/"+m_stopEndPoint).append("/suspend"), + COMMAND_HIDE, emptyPayload, responseHeaders, responseBody ); + return status; +} + int DialServer::getHttpResponseHeader( string &responseHeaders, string &header, diff --git a/client/DialServer.h b/client/DialServer.h index ccd37e4..2937630 100644 --- a/client/DialServer.h +++ b/client/DialServer.h @@ -26,6 +26,9 @@ #ifndef DIALSERVER_H #define DIALSERVER_H +#include +#include + //#define DEBUG #ifdef DEBUG #define ATRACE(...) printf(__VA_ARGS__) @@ -126,6 +129,21 @@ public: string &responseHeaders, string &responseBody ); + /** + * Hide a DIAL application + * + * @param[in] application Name of the application to launch + * @param[out] responseHeaders Returns the HTTP response headers + * @param[out] responseBody Returns the HTTP response body + * + * @return 0 if successful, !0 otherwise + */ + + int hideApplication( + string &application, + string &responseHeaders, + string &responseBody ); + /** * Get the status of a DIAL application * diff --git a/client/main.cpp b/client/main.cpp index a1a85f0..ff6041b 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -222,15 +222,17 @@ int handleUser(DialDiscovery *pDial) { memset(buf, 0, 80); printf("0. Rescan and list DIAL servers\n"); printf("1. Launch Netflix\n"); - printf("2. Kill Netflix\n"); - printf("3. Netflix status\n"); - printf("4. Launch YouTube\n"); - printf("5. Kill YouTube\n"); - printf("6. YouTube status\n"); - printf("7. Run conformance tests\n"); - printf("8. Wake up on lan/wlan\n"); - printf("9. QUIT\n"); - printf("Command (0:1:2:3:4:5:6:7:8:9): "); + printf("2. Hide Netflix\n"); + printf("3. Kill Netflix\n"); + printf("4. Netflix status\n"); + printf("5. Launch YouTube\n"); + printf("6. Hide YouTube\n"); + printf("7. Kill YouTube\n"); + printf("8. YouTube status\n"); + printf("9. Run conformance tests\n"); + printf("10. Wake up on lan/wlan\n"); + printf("11. QUIT\n"); + printf("Command (0:1:2:3:4:5:6:7:8:9:10:11): "); scanf("%s", buf); switch( atoi(buf) ) { @@ -244,34 +246,42 @@ int handleUser(DialDiscovery *pDial) { pServer->launchApplication( netflix, payload, responseHeaders, responseBody ); break; case 2: + printf("Hide Netflix\n"); + pServer->hideApplication( netflix, responseHeaders, responseBody ); + break; + case 3: printf("Kill Netflix\n"); pServer->stopApplication( netflix, responseHeaders ); break; - case 3: + case 4: printf("Netflix Status: \n"); pServer->getStatus( netflix, responseHeaders, responseBody ); printf("RESPONSE: \n%s\n", responseBody.c_str()); break; - case 4: + case 5: printf("Launch YouTube\n"); pServer->launchApplication( youtube, payload, responseHeaders, responseBody ); break; - case 5: + case 6: + printf("Hide YouTube\n"); + pServer->hideApplication( youtube, responseHeaders, responseBody ); + break; + case 7: printf("Kill YouTube\n"); pServer->stopApplication( youtube, responseHeaders ); break; - case 6: + case 8: printf("YouTube Status: \n"); pServer->getStatus( youtube, responseHeaders, responseBody ); break; - case 7: + case 9: runConformance(); break; - case 8: + case 10: printf("Sending the magic packet\n"); sendMagic(pServer->getMacAddress()); break; - case 9: + case 11: processInput = 0; processInputOuter = 0; break; diff --git a/server/dial_server.c b/server/dial_server.c index a357907..375851d 100644 --- a/server/dial_server.c +++ b/server/dial_server.c @@ -275,6 +275,34 @@ static void handle_app_stop(struct mg_connection *conn, ds_unlock(ds); } +static void handle_app_hide(struct mg_connection *conn, + const struct mg_request_info *request_info, + const char *app_name, + const char *origin_header) { + DIALApp *app; + DIALServer *ds = request_info->user_data; + int canStop = 0; + + ds_lock(ds); + app = *find_app(ds, app_name); + + // update the application state + if (app) { + app->state = app->callbacks.status_cb(ds, app_name, app->run_id, + &canStop, app->callback_data); + } + + if (!app || app->state != kDIALStatusRunning) { + mg_send_http_error(conn, 404, "Not Found", "Not Found"); + } else { + // not implemented in reference + fprintf(stderr, "Hide not implemented for reference."); + mg_send_http_error(conn, 501, "Not Implemented", + "Not Implemented"); + } + ds_unlock(ds); +} + static void handle_dial_data(struct mg_connection *conn, const struct mg_request_info *request_info, const char *app_name, @@ -411,6 +439,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" static void *options_response(DIALServer *ds, struct mg_connection *conn, char *host_header, char *origin_header, const char* app_name, const char* methods) { @@ -498,8 +527,28 @@ static void *request_handler(enum mg_event event, struct mg_connection *conn, mg_send_http_error(conn, 501, "Not Implemented", "Not Implemented"); } + } + // URI that ends with HIDE_URI + else if (!strncmp(request_info->uri + strlen(request_info->uri) - strlen(HIDE_URI), HIDE_URI, + strlen(HIDE_URI))) { + char app_name[256] = {0, }; // assuming the application name is not over 256 chars. + strncpy(app_name, request_info->uri + strlen(APPS_URI), + ((strlen(request_info->uri) - strlen(RUN_URI) - strlen(HIDE_URI)) - (sizeof(APPS_URI) - 1))); + + if (!strcmp(request_info->request_method, "OPTIONS")) { + return options_response(ds, conn, host_header, origin_header, app_name, "POST, OPTIONS"); + } + + if (app_name[0] != '\0' + && !strcmp(request_info->request_method, "POST")) { + handle_app_hide(conn, request_info, app_name, origin_header); + }else{ + mg_send_http_error(conn, 501, "Not Implemented", + "Not Implemented"); + } + } // URI is of the form */app_name/dial_data - } else if (strstr(request_info->uri, DIAL_DATA_URI)) { + else if (strstr(request_info->uri, DIAL_DATA_URI)) { char laddr[INET6_ADDRSTRLEN]; const struct sockaddr_in *addr = (struct sockaddr_in *) &request_info->remote_addr;