mirror of
https://github.com/nasa/trick.git
synced 2024-12-19 21:27:54 +00:00
Comments and rearrangment for clarity.
This commit is contained in:
parent
2e08379e42
commit
63605da069
@ -28,6 +28,7 @@ LIBRARY DEPENDENCIES:
|
||||
"values" : []
|
||||
}
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef WSSESSION_HH
|
||||
#define WSSESSION_HH
|
||||
|
||||
@ -40,6 +41,7 @@ LIBRARY DEPENDENCIES:
|
||||
class VariableServerSession : public WebSocketSession {
|
||||
public:
|
||||
VariableServerSession(struct mg_connection *nc);
|
||||
~VariableServerSession();
|
||||
void stageData(); /* -- base */
|
||||
void sendMessage(); /* -- base */
|
||||
int handleMessage(std::string); /* -- base */
|
||||
|
@ -18,7 +18,7 @@ class VariableServerVariable {
|
||||
|
||||
public:
|
||||
VariableServerVariable( REF2* variableType);
|
||||
~VariableServerVariable();
|
||||
~VariableServerVariable();
|
||||
const char* getName();
|
||||
void stageValue();
|
||||
void writeValue( std::ostream& chkpnt_os );
|
||||
|
@ -12,51 +12,112 @@ LIBRARY DEPENDENCIES:
|
||||
#include "../include/VariableServerSession.hh"
|
||||
#include "../include/simpleJSON.hh"
|
||||
|
||||
// CONSTRUCTOR
|
||||
VariableServerSession::VariableServerSession( struct mg_connection *nc ) : WebSocketSession(nc) {
|
||||
intervalTimeTics = exec_get_time_tic_value(); // Default time interval is one second.
|
||||
nextTime = LLONG_MAX;
|
||||
cyclicSendEnabled = false;
|
||||
}
|
||||
|
||||
// DESTRUCTOR
|
||||
VariableServerSession::~VariableServerSession() {
|
||||
clear();
|
||||
}
|
||||
|
||||
// Base class virtual function.
|
||||
void VariableServerSession::stageData() {
|
||||
long long simulation_time_tics = exec_get_time_tics();
|
||||
if ( cyclicSendEnabled && ( simulation_time_tics >= nextTime )) {
|
||||
stageVariableValues();
|
||||
}
|
||||
nextTime = (simulation_time_tics - (simulation_time_tics % intervalTimeTics) + intervalTimeTics);
|
||||
}
|
||||
|
||||
// Base class virtual function.
|
||||
void VariableServerSession::sendMessage() {
|
||||
std::vector<VariableServerVariable*>::iterator it;
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "{ \"msg_type\" : \"values\",\n";
|
||||
ss << " \"time\" : " << std::setprecision(16) << stageTime << ",\n";
|
||||
ss << " \"values\" : [\n";
|
||||
|
||||
for (it = sessionVariables.begin(); it != sessionVariables.end(); it++ ) {
|
||||
if (it != sessionVariables.begin()) ss << ",\n";
|
||||
(*it)->writeValue(ss);
|
||||
}
|
||||
ss << "]}" << std::endl;
|
||||
std::string tmp = ss.str();
|
||||
const char * message = tmp.c_str();
|
||||
mg_send_websocket_frame(connection, WEBSOCKET_OP_TEXT, message, strlen(message));
|
||||
}
|
||||
|
||||
// Base class virtual function.
|
||||
int VariableServerSession::handleMessage(std::string client_msg) {
|
||||
|
||||
int status = 0;
|
||||
std::vector<Member*> members = parseJSON(client_msg.c_str());
|
||||
std::vector<Member*>::iterator it;
|
||||
const char *cmd;
|
||||
const char *var_name;
|
||||
int period;
|
||||
|
||||
for (it = members.begin(); it != members.end(); it++ ) {
|
||||
if (strcmp((*it)->key, "cmd") == 0) {
|
||||
cmd = (*it)->valText;
|
||||
} else if (strcmp((*it)->key, "var_name") == 0) {
|
||||
var_name = (*it)->valText;
|
||||
} else if (strcmp((*it)->key, "period") == 0) {
|
||||
period = atoi((*it)->valText);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd == NULL) {
|
||||
printf ("No \"cmd\" member found in client message.\n");
|
||||
status = 1;
|
||||
} else if (strcmp(cmd, "var_add") == 0) {
|
||||
addVariable( strdup(var_name) );
|
||||
} else if ( strcmp(cmd, "var_cycle") == 0 ) {
|
||||
setTimeInterval(period);
|
||||
} else if ( strcmp(cmd, "var_pause") == 0 ) {
|
||||
pause();
|
||||
} else if ( strcmp(cmd, "var_unpause") == 0 ) {
|
||||
unpause();
|
||||
} else if ( strcmp(cmd, "var_send") == 0 ) {
|
||||
stageVariableValues();
|
||||
sendMessage();
|
||||
} else if ( strcmp(cmd, "var_clear") == 0 ) {
|
||||
clear();
|
||||
} else if ( strcmp(cmd, "var_exit") == 0 ) {
|
||||
//TODO
|
||||
// nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
} else {
|
||||
sendErrorMessage("Unknown Command: \"%s\".\n", cmd);
|
||||
status = 1;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// #include "trick/input_processor_proto.h"
|
||||
// for( ii = 0 , jj = 0 ; ii <= msg_len ; ii++ ) {
|
||||
// if ( incoming_msg[ii] != '\r' ) {
|
||||
// stripped_msg[jj++] = incoming_msg[ii] ;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// ip_parse(stripped_msg); /* returns 0 if no parsing error */
|
||||
|
||||
|
||||
// Remove characters from a string
|
||||
// str.erase(std::remove(str.begin(), str.end(), '\r'), str.end());
|
||||
|
||||
|
||||
|
||||
|
||||
void VariableServerSession::setTimeInterval(unsigned int milliseconds) {
|
||||
intervalTimeTics = exec_get_time_tic_value() * milliseconds / 1000;
|
||||
}
|
||||
|
||||
int VariableServerSession::bad_ref_int = 0 ;
|
||||
|
||||
REF2* VariableServerSession::make_error_ref(const char* in_name) {
|
||||
REF2* new_ref;
|
||||
new_ref = (REF2*)calloc(1, sizeof(REF2));
|
||||
new_ref->reference = strdup(in_name) ;
|
||||
new_ref->units = NULL ;
|
||||
new_ref->address = (char *)&bad_ref_int ;
|
||||
new_ref->attr = (ATTRIBUTES*)calloc(1, sizeof(ATTRIBUTES)) ;
|
||||
new_ref->attr->type = TRICK_NUMBER_OF_TYPES ;
|
||||
new_ref->attr->units = (char *)"--" ;
|
||||
new_ref->attr->size = sizeof(int) ;
|
||||
return new_ref;
|
||||
}
|
||||
|
||||
#define MAX_MSG_SIZE 4096
|
||||
int VariableServerSession::sendErrorMessage(const char* fmt, ... ) {
|
||||
char errText[MAX_MSG_SIZE];
|
||||
char msgText[MAX_MSG_SIZE];
|
||||
va_list args;
|
||||
|
||||
errText[0]=0;
|
||||
msgText[0]=0;
|
||||
|
||||
va_start(args, fmt);
|
||||
(void) vsnprintf(errText, MAX_MSG_SIZE, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
sprintf(msgText, "{ \"msg_type\" : \"error\",\n"
|
||||
" \"error\" : \"%s\"}\n", errText);
|
||||
|
||||
mg_send_websocket_frame(connection, WEBSOCKET_OP_TEXT, msgText, strlen(msgText));
|
||||
return (0);
|
||||
}
|
||||
|
||||
void VariableServerSession::addVariable(char* vname){
|
||||
REF2 * new_ref ;
|
||||
new_ref = ref_attributes(vname);
|
||||
@ -96,32 +157,6 @@ void VariableServerSession::stageVariableValues() {
|
||||
}
|
||||
}
|
||||
|
||||
void VariableServerSession::stageData() {
|
||||
long long simulation_time_tics = exec_get_time_tics();
|
||||
if ( cyclicSendEnabled && ( simulation_time_tics >= nextTime )) {
|
||||
stageVariableValues();
|
||||
}
|
||||
nextTime = (simulation_time_tics - (simulation_time_tics % intervalTimeTics) + intervalTimeTics);
|
||||
}
|
||||
|
||||
void VariableServerSession::sendMessage() {
|
||||
std::vector<VariableServerVariable*>::iterator it;
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "{ \"msg_type\" : \"values\",\n";
|
||||
ss << " \"time\" : " << std::setprecision(16) << stageTime << ",\n";
|
||||
ss << " \"values\" : [\n";
|
||||
|
||||
for (it = sessionVariables.begin(); it != sessionVariables.end(); it++ ) {
|
||||
if (it != sessionVariables.begin()) ss << ",\n";
|
||||
(*it)->writeValue(ss);
|
||||
}
|
||||
ss << "]}" << std::endl;
|
||||
std::string tmp = ss.str();
|
||||
const char * message = tmp.c_str();
|
||||
mg_send_websocket_frame(connection, WEBSOCKET_OP_TEXT, message, strlen(message));
|
||||
}
|
||||
|
||||
void VariableServerSession::pause() { cyclicSendEnabled = false; }
|
||||
|
||||
void VariableServerSession::unpause() { cyclicSendEnabled = true; }
|
||||
@ -137,46 +172,37 @@ void VariableServerSession::clear() {
|
||||
|
||||
void VariableServerSession::exit() {}
|
||||
|
||||
int VariableServerSession::handleMessage(std::string client_msg) {
|
||||
int VariableServerSession::bad_ref_int = 0 ;
|
||||
|
||||
int status = 0;
|
||||
std::vector<Member*> members = parseJSON(client_msg.c_str());
|
||||
std::vector<Member*>::iterator it;
|
||||
const char *cmd;
|
||||
const char *var_name;
|
||||
int period;
|
||||
#define MAX_MSG_SIZE 4096
|
||||
int VariableServerSession::sendErrorMessage(const char* fmt, ... ) {
|
||||
char errText[MAX_MSG_SIZE];
|
||||
char msgText[MAX_MSG_SIZE];
|
||||
va_list args;
|
||||
|
||||
for (it = members.begin(); it != members.end(); it++ ) {
|
||||
if (strcmp((*it)->key, "cmd") == 0) {
|
||||
cmd = (*it)->valText;
|
||||
} else if (strcmp((*it)->key, "var_name") == 0) {
|
||||
var_name = (*it)->valText;
|
||||
} else if (strcmp((*it)->key, "period") == 0) {
|
||||
period = atoi((*it)->valText);
|
||||
}
|
||||
}
|
||||
errText[0]=0;
|
||||
msgText[0]=0;
|
||||
|
||||
if (cmd == NULL) {
|
||||
printf ("No \"cmd\" member found in client message.\n");
|
||||
status = 1;
|
||||
} else if (strcmp(cmd, "var_add") == 0) {
|
||||
addVariable( strdup(var_name) );
|
||||
} else if ( strcmp(cmd, "var_cycle") == 0 ) {
|
||||
setTimeInterval(period);
|
||||
} else if ( strcmp(cmd, "var_pause") == 0 ) {
|
||||
pause();
|
||||
} else if ( strcmp(cmd, "var_unpause") == 0 ) {
|
||||
unpause();
|
||||
} else if ( strcmp(cmd, "var_send") == 0 ) {
|
||||
stageVariableValues();
|
||||
sendMessage();
|
||||
} else if ( strcmp(cmd, "var_clear") == 0 ) {
|
||||
clear();
|
||||
} else if ( strcmp(cmd, "var_exit") == 0 ) {
|
||||
//TODO
|
||||
} else {
|
||||
sendErrorMessage("Unknown Command: \"%s\".\n", cmd);
|
||||
status = 1;
|
||||
}
|
||||
return status;
|
||||
va_start(args, fmt);
|
||||
(void) vsnprintf(errText, MAX_MSG_SIZE, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
sprintf(msgText, "{ \"msg_type\" : \"error\",\n"
|
||||
" \"error\" : \"%s\"}\n", errText);
|
||||
|
||||
mg_send_websocket_frame(connection, WEBSOCKET_OP_TEXT, msgText, strlen(msgText));
|
||||
return (0);
|
||||
}
|
||||
|
||||
REF2* VariableServerSession::make_error_ref(const char* in_name) {
|
||||
REF2* new_ref;
|
||||
new_ref = (REF2*)calloc(1, sizeof(REF2));
|
||||
new_ref->reference = strdup(in_name) ;
|
||||
new_ref->units = NULL ;
|
||||
new_ref->address = (char *)&bad_ref_int ;
|
||||
new_ref->attr = (ATTRIBUTES*)calloc(1, sizeof(ATTRIBUTES)) ;
|
||||
new_ref->attr->type = TRICK_NUMBER_OF_TYPES ;
|
||||
new_ref->attr->units = (char *)"--" ;
|
||||
new_ref->attr->size = sizeof(int) ;
|
||||
return new_ref;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ static const struct mg_str s_put_method = MG_MK_STR("PUT");
|
||||
static const struct mg_str s_delete_method = MG_MK_STR("DELETE");
|
||||
static const struct mg_str http_api_prefix = MG_MK_STR("/api/http/");
|
||||
static const struct mg_str ws_api_prefix = MG_MK_STR("/api/ws/");
|
||||
|
||||
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||
|
||||
http_message *hm = (struct http_message *)ev_data;
|
||||
@ -51,8 +52,9 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||
} break;
|
||||
case MG_EV_POLL: {
|
||||
// The MG_EV_POLL event is sent to all connections for each invocation of mg_mgr_poll(),
|
||||
// called periodically by the threaded function connectionAttendant() [below].
|
||||
// Send websocket messages to the client (web browser).
|
||||
// called periodically by the threaded function connectionAttendant() [below] when it is
|
||||
// signaled (serviceConnections) from the http_top_of_frame job.
|
||||
// This is when we send websocket messages to the client (web browser).
|
||||
if (nc->flags & MG_F_IS_WEBSOCKET) {
|
||||
httpServer->sendWebSocketSessionMessages(nc);
|
||||
}
|
||||
@ -99,12 +101,15 @@ static void* connectionAttendant (void* arg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Install a WebSocketSessionMaker with a name (key) by which it can be retrieved.
|
||||
void HTTP_Server::installWebSocketSessionMaker(std::string name, WebSocketSessionMaker maker) {
|
||||
pthread_mutex_lock(&WebSocketSessionMakerMapLock);
|
||||
WebSocketSessionMakerMap.insert(std::pair<std::string, WebSocketSessionMaker>(name, maker));
|
||||
pthread_mutex_unlock(&WebSocketSessionMakerMapLock);
|
||||
}
|
||||
|
||||
// Lookup and call the WebSocketSessionMaker function by name, end execute it to create and return
|
||||
// (a pointer to) a WebSocketSession.
|
||||
WebSocketSession* HTTP_Server::makeWebSocketSession(struct mg_connection *nc, std::string name) {
|
||||
std::map<std::string, WebSocketSessionMaker>::iterator iter;
|
||||
iter = WebSocketSessionMakerMap.find(name);
|
||||
@ -117,12 +122,15 @@ WebSocketSession* HTTP_Server::makeWebSocketSession(struct mg_connection *nc, st
|
||||
}
|
||||
}
|
||||
|
||||
void HTTP_Server::installHTTPGEThandler(std::string APIname, httpMethodHandler handler) {
|
||||
// Install an httpMethodHandler with a name (key) by which it can be retrieved.
|
||||
void HTTP_Server::installHTTPGEThandler(std::string handlerName, httpMethodHandler handler) {
|
||||
pthread_mutex_lock(&httpGETHandlerMapLock);
|
||||
httpGETHandlerMap.insert(std::pair<std::string, httpMethodHandler>(APIname, handler));
|
||||
httpGETHandlerMap.insert(std::pair<std::string, httpMethodHandler>(handlerName, handler));
|
||||
pthread_mutex_unlock(&httpGETHandlerMapLock);
|
||||
}
|
||||
|
||||
// Lookup the appropriate httpMethodHandler by name, and execute it for the given connection
|
||||
// and http_message.
|
||||
void HTTP_Server::handleHTTPGETrequest(struct mg_connection *nc, http_message *hm, std::string handlerName) {
|
||||
std::map<std::string, httpMethodHandler>::iterator iter;
|
||||
iter = httpGETHandlerMap.find(handlerName);
|
||||
@ -134,9 +142,9 @@ void HTTP_Server::handleHTTPGETrequest(struct mg_connection *nc, http_message *h
|
||||
}
|
||||
}
|
||||
|
||||
// Find the session that goes with the given websocket connection,
|
||||
// and tell it to send its values to the client (web browser).
|
||||
void HTTP_Server::sendWebSocketSessionMessages(struct mg_connection *nc) {
|
||||
// Find the session that goes with the given websocket connection,
|
||||
// and tell it to send its values to the client (web browser).
|
||||
std::map<mg_connection*, WebSocketSession*>::iterator iter;
|
||||
iter = sessionMap.find(nc);
|
||||
if (iter != sessionMap.end()) {
|
||||
@ -145,6 +153,8 @@ void HTTP_Server::sendWebSocketSessionMessages(struct mg_connection *nc) {
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the WebSocketSession associated with the given connection-pointer, and
|
||||
// erase its pointer from the sessionMap.
|
||||
void HTTP_Server::deleteWebSocketSession(struct mg_connection *nc) {
|
||||
std::map<mg_connection*, WebSocketSession*>::iterator iter;
|
||||
iter = sessionMap.find(nc);
|
||||
@ -154,6 +164,9 @@ void HTTP_Server::deleteWebSocketSession(struct mg_connection *nc) {
|
||||
sessionMap.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup the WebSocketSession associated with the given connection-pointer, and pass
|
||||
// the given message to it.
|
||||
void HTTP_Server::handleWebSocketClientMessage(struct mg_connection *nc, std::string msg) {
|
||||
std::map<mg_connection*, WebSocketSession*>::iterator iter;
|
||||
iter = sessionMap.find(nc);
|
||||
@ -163,36 +176,40 @@ void HTTP_Server::handleWebSocketClientMessage(struct mg_connection *nc, std::st
|
||||
}
|
||||
}
|
||||
|
||||
// Install a WebSocketSession with a connection-pointer (key) by which it can be retrieved.
|
||||
void HTTP_Server::addWebSocketSession(struct mg_connection *nc, WebSocketSession* session) {
|
||||
pthread_mutex_lock(&sessionMapLock);
|
||||
sessionMap.insert( std::pair<mg_connection*, WebSocketSession*>(nc, session) );
|
||||
pthread_mutex_unlock(&sessionMapLock);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Trick Sim Interface Functions
|
||||
// =========================================================================
|
||||
|
||||
int HTTP_Server::http_default_data() {
|
||||
port = "8888";
|
||||
document_root = "www";
|
||||
shutting_down = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// WebSocketSessionMaker function for a VariableServerSession.
|
||||
static WebSocketSession* makeVariableServerSession( struct mg_connection *nc ) {
|
||||
return new VariableServerSession(nc);
|
||||
}
|
||||
|
||||
int HTTP_Server::http_init() {
|
||||
// =========================================================================
|
||||
// Trick Sim Interface Functions
|
||||
// =========================================================================
|
||||
|
||||
http_server_options.document_root = document_root;
|
||||
http_server_options.enable_directory_listing = "yes";
|
||||
// Trick "default_data" job.
|
||||
int HTTP_Server::http_default_data() {
|
||||
port = "8888";
|
||||
document_root = "www";
|
||||
shutting_down = false;
|
||||
|
||||
installHTTPGEThandler("vs_connections", &handle_HTTP_GET_vs_connections);
|
||||
installHTTPGEThandler("alloc_info", &handle_HTTP_GET_alloc_info);
|
||||
installWebSocketSessionMaker("VariableServer", &makeVariableServerSession);
|
||||
//installWebSocketSessionMaker("VariableServer", [](struct mg_connection *nc) -> WebSocketSession* { return new VariableServerSession(nc); } );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Trick "initialization" job.
|
||||
int HTTP_Server::http_init() {
|
||||
|
||||
http_server_options.document_root = document_root;
|
||||
http_server_options.enable_directory_listing = "yes";
|
||||
|
||||
mg_mgr_init( &mgr, NULL );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user