/* Virginia Tech Cognitive Radio Open Source Systems * Virginia Tech, 2009 * * LICENSE INFORMATION GOES HERE */ /* Inter-component communication handled by sockets and FD's. * Server support has been completely implemented and tested. * * Services are stored in a SQLite DB by the ID of the CE that registered them. Service * support has been completely implemented and tested. * * Missions are loaded from an XML file, connected with services provided by components, * and run. See the documentation for the "PerformActiveMission" below for important * info. Mission support has been completely implemented but mostly untested * (except for the XML parsing, which has been fully tested). * * It is important that in the XML configuration file, inputs and outputs are listed * in the order that they appear. See the documentation for the "PerformActiveMission" * method for more information. * * */ #include #include #include #include #include /*#include "../../trunk/src/include/vtcross/common.h" #include "../../trunk/src/include/vtcross/components.h" #include "../../trunk/src/include/vtcross/containers.h" #include "../../trunk/src/include/vtcross/debug.h" #include "../../trunk/src/include/vtcross/error.h" #include "../../trunk/src/include/vtcross/socketcomm.h"*/ #include "vtcross/common.h" #include "vtcross/components.h" #include "vtcross/containers.h" #include "vtcross/debug.h" #include "vtcross/error.h" #include "vtcross/socketcomm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*#include "../../trunk/src/include/tinyxml/tinyxml.h" #include "../../trunk/src/include/tinyxml/tinystr.h"*/ #include "tinyxml/tinyxml.h" #include "tinyxml/tinystr.h" #include "sqlite3.h" //#include "sqlite3ext.h" typedef struct services_s * services_DB; struct services_s { char filename[64]; char tablename[64]; char command[2048]; sqlite3 *db; unsigned int num_columns; }; services_DB _services_DB; const char *_SML_Config; int callback(void *notUsed, int argc, char **argv, char **azColName){ int i; for(i=0; icommand, "drop table "); strcat(_services_DB->command, _services_DB->tablename); int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg); if( rc!=SQLITE_OK && rc!=101 ) fprintf(stderr, "SQL error: %s\n", errorMsg); strcpy(_services_DB->command, "vacuum"); rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg); if( rc!=SQLITE_OK && rc!=101 ) fprintf(stderr, "SQL error: %s\n", errorMsg); free(_services_DB); } ServiceManagementLayer::ServiceManagementLayer(const char* SML_Config, \ const char* serverName, const char* serverPort) { LOG("Creating Service Management Layer.\n"); _SML_Config = SML_Config; ConnectToShell(serverName, serverPort); CE_List = (CE_Reg *) malloc(10*sizeof(struct CE_Reg)); CE_List = new CE_Reg[10]; miss = new Mission[10]; for(int i = 0; i < 10; i++) miss[i].services = new Service[20]; Current_ID = 0; LoadConfiguration(SML_Config, miss); CreateServicesDB(); } //VERIFIED May 26 void ServiceManagementLayer::CreateServicesDB() { _services_DB = (services_DB) malloc(sizeof(struct services_s)); char *errorMsg; // create database // copy filename unsigned int i=0; strcpy(_services_DB->filename, "Services_Table"); // execute create database command // database handle //_services_DB->db = NULL; sqlite3_open(_services_DB->filename, &(_services_DB->db)); char* cols[] = {(char *)"ID_Num", (char *)"Service_Name"}; // create table // copy tablename strcpy(_services_DB->tablename, "Services"); // number of columns in the table _services_DB->num_columns = 2; // generate command strcpy(_services_DB->command, "CREATE TABLE "); strcat(_services_DB->command, _services_DB->tablename); strcat(_services_DB->command, "("); //strcat(_services_DB->command, "SRVID INTEGER PRIMARY KEY, "); strcat(_services_DB->command, cols[0]); strcat(_services_DB->command, " INT, "); strcat(_services_DB->command, cols[1]); strcat(_services_DB->command, " TEXT"); strcat(_services_DB->command, ");"); // execute create table command sqlite3_stmt *ppStmt; /* OUT: Statement handle */ const char *pzTail; /* OUT: Pointer to unused portion of zSql */ int rc = sqlite3_prepare_v2(_services_DB->db, _services_DB->command, 128, &ppStmt, &pzTail); if( rc!=SQLITE_OK && rc!=101 ) printf("SQL error(1): %d\n", rc); rc = sqlite3_step(ppStmt); if( rc!=SQLITE_OK && rc!=101 ) printf("SQL error(2): %d\n", rc); } void ServiceManagementLayer::SendComponentType() { SendMessage(shellSocketFD, "response_sml"); LOG("SML responded to GetRemoteComponentType query.\n"); } void ServiceManagementLayer::ConnectToShell(const char* serverName, \ const char* serverPort) { shellSocketFD = ClientSocket(serverName, serverPort); //Set the shell socket to non-block mode /*int oldflags = fcntl (shellSocketFD, F_GETFL, 0); oldflags |= O_NONBLOCK; fcntl (shellSocketFD, F_SETFL, oldflags);*/ RegisterComponent(); } void ServiceManagementLayer::MessageHandler(int32_t ID) { char buffer[256]; memset(buffer, 0, 256); int32_t _FD; //printf("ID= %d\n", ID); if(ID != -1) _FD = CE_List[ID].FD; else _FD = shellSocketFD; //printf("FD=%d, shellFD=%d", _FD, shellSocketFD); ssize_t msgLength = recv(_FD, buffer, 256, MSG_PEEK); if(msgLength == 0){ //printf("Error reading from socket.\n"); //sleep(5); return; } size_t i; for(i = 0; i < 256; i++) { if(strcmp(&buffer[i], "\0") == 0) break; } // Read the message into msgBuffer recv(_FD, buffer, i + 1, 0); //printf("********* %s **********\n", buffer); // TODO // If we send integer op codes rather than strings, this process will be // MUCH faster since instead of donig string compares we can simply // switch on the integer value... /*if(strcmp(buffer, "register_service") == 0) { if(strcmp(buffer, "policy_geo") == 0) { } else if(strcmp(buffer, "policy_time") == 0) { } else if(strcmp(buffer, "policy_spectrum") == 0) { } else if(strcmp(buffer, "policy_spacial") == 0) { } } else if(strcmp(buffer, "deregister_service") == 0) { if(strcmp(buffer, "policy_geo") == 0) { } else if(strcmp(buffer, "policy_time") == 0) { } else if(strcmp(buffer, "policy_spectrum") == 0) { } else if(strcmp(buffer, "policy_spacial") == 0) { } }*/ if(strcmp(buffer, "query_component_type") == 0) { SendComponentType(); } else if(strcmp(buffer, "reset_sml") == 0) { Reset(); } else if(strcmp(buffer, "shutdown_sml") == 0) { Shutdown(); } else if(strcmp(buffer, "register_engine_cognitive") == 0) { RegisterCognitiveEngine(ID); } else if(strcmp(buffer, "register_service") == 0) { ReceiveServices(ID); } else if(strcmp(buffer, "send_component_type") == 0) { SendComponentType(); } else if(strcmp(buffer, "list_services") == 0) { ListServices(); } else if(strcmp(buffer, "set_active_mission") == 0) { SetActiveMission(); } else if(strcmp(buffer, "request_optimization") == 0) { PerformActiveMission(); } } void ServiceManagementLayer::Shutdown() { DeregisterComponent(); } void ServiceManagementLayer::Reset() { DeregisterComponent(); LoadConfiguration(_SML_Config, miss); } void ServiceManagementLayer::RegisterComponent() { SendMessage(shellSocketFD, "register_sml"); LOG("ServiceManagementLayer:: Registration message sent.\n"); } void ServiceManagementLayer::DeregisterComponent() { SendMessage(shellSocketFD, "deregister_sml"); LOG("ServiceManagementLayer:: Deregistration message sent.\n"); shutdown(shellSocketFD, 2); close(shellSocketFD); shellSocketFD = -1; LOG("ServiceManagementLayer:: Shell socket closed.\n"); } /* Streams config data directly from the shell to the CE, and checks * for an "ack" message from the CE after every sent message * to know when to stop communication. */ void ServiceManagementLayer::TransferRadioConfiguration(int32_t ID) { struct timeval selTimeout; fd_set sockSet; int32_t rc = 0; char buffer[256]; //Send data until the CE sends an ACK message back while(rc==0){ memset(buffer, 0, 256); //Receive data from Shell ReadMessage(shellSocketFD, buffer); //Send data to CE SendMessage(CE_List[ID].FD, buffer); FD_ZERO(&sockSet); FD_SET(CE_List[ID].FD, &sockSet); selTimeout.tv_sec = 0; selTimeout.tv_usec = 0; //Check if there is a message on the CE socket ready to be processed rc=select(CE_List[ID].FD + 1, &sockSet, NULL, NULL, &selTimeout); } memset(buffer, 0, 256); ReadMessage(CE_List[ID].FD, buffer); SendMessage(shellSocketFD, buffer); } //Simmilar to TransferRadioConfig, just with Experience data void ServiceManagementLayer::TransferExperience(int32_t ID) { struct timeval selTimeout; fd_set sockSet; int32_t rc = 0; char buffer[256]; //Send data until the CE sends an ACK message back while(rc==0){ memset(buffer, 0, 256); //Receive data from Shell ReadMessage(shellSocketFD, buffer); //Send data to CE SendMessage(CE_List[ID].FD, buffer); FD_ZERO(&sockSet); FD_SET(CE_List[ID].FD, &sockSet); selTimeout.tv_sec = 0; selTimeout.tv_usec = 0; //Check if there is a message on the CE socket ready to be processed rc = select(CE_List[ID].FD + 1, &sockSet, NULL, NULL, &selTimeout); } memset(buffer, 0, 256); ReadMessage(CE_List[ID].FD, buffer); SendMessage(shellSocketFD, buffer); } //VERIFIED May 26 void ServiceManagementLayer::ReceiveServices(int32_t ID) { char buffer[256]; memset(buffer, 0, 256); ReadMessage(CE_List[ID].FD, buffer); char* cols[] = {(char *)"ID_Num", (char *)"Service_Name"}; // generate command //printf("%s\n", _services_DB->command); strcpy(_services_DB->command, "insert into "); strcat(_services_DB->command, _services_DB->tablename); strcat(_services_DB->command, " ("); strcat(_services_DB->command, cols[0]); strcat(_services_DB->command, ", "); strcat(_services_DB->command, cols[1]); strcat(_services_DB->command, ") "); strcat(_services_DB->command, " values("); sprintf(_services_DB->command, "%s%d", _services_DB->command, ID); strcat(_services_DB->command, ", '"); strcat(_services_DB->command, buffer); strcat(_services_DB->command, "');"); //printf("search command: %s\n", _services_DB->command); // execute add command char *errorMsg; int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg); if( rc!=SQLITE_OK && rc!=101 ) fprintf(stderr, "SQL error: %s\n", errorMsg); printf("SML: Registering service '%s' from component number '%d'\n", buffer, ID); } //This method associates the services that components provide with the services that are requested in the mission //Each service in the mission is given the ID and FD of a component that has registered to provide that service //Deregistration is okay until this method is called without a reload, but if deregistration occurs after this // method is called it needs to be called again even if other engines also provide the services //Verified May 29 void ServiceManagementLayer::SetActiveMission() { char buffer[256]; memset(buffer, 0, 256); ReadMessage(shellSocketFD, buffer); int32_t missID = atoi(buffer); for(activeMission = 0; activeMission < 10; activeMission++) { if(miss[activeMission].missionID == missID) break; } for(int i = 0; i < miss[activeMission].numServices; i++) { if(miss[activeMission].services[i].name.compare("if") && miss[activeMission].services[i].name.compare("while")){ strcpy(_services_DB->command, "select "); strcat(_services_DB->command, _services_DB->tablename); strcat(_services_DB->command, ".* from "); strcat(_services_DB->command, _services_DB->tablename); strcat(_services_DB->command, " where Service_Name=="); sprintf(_services_DB->command, "%s'%s';", _services_DB->command, miss[activeMission].services[i].name.c_str()); sqlite3_stmt * pStatement; int rc = sqlite3_prepare_v2(_services_DB->db, _services_DB->command, -1, &pStatement, NULL); if (rc == SQLITE_OK){ if (sqlite3_step(pStatement) == SQLITE_ROW) miss[activeMission].services[i].componentID = sqlite3_column_int(pStatement, 0); else { printf("services_DB:: Mission requires service not provided by any connected component.\n"); rc=31337; } } else { printf("services_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_services_DB->command); } sqlite3_finalize(pStatement); miss[activeMission].services[i].socketFD = CE_List[miss[activeMission].services[i].componentID].FD;} } printf("\nhere ---%d, %d---\n", miss[activeMission].services[0].componentID, miss[activeMission].services[2].componentID); } //This is a helper method for the "PerformActiveMission" function //It takes the ID's of a source and a destination and does a raw transfer between them //It knows when to stop when an "ack" signal returns from the destination component //An ID of "-1" coresponds to the shell void ServiceManagementLayer::TransactData(int32_t sourceID, int32_t destID) { printf("transact occuring between %d and %d\n", sourceID, destID); int32_t FD_src, FD_dest; struct timeval selTimeout; if(sourceID==-1) FD_src=shellSocketFD; else FD_src=CE_List[sourceID].FD; if(destID==-1) FD_dest=shellSocketFD; else FD_dest=CE_List[destID].FD; int32_t rc = 0; fd_set sockSet; char buffer[256]; //Send data until the CE sends an ACK message back while(rc==0){ memset(buffer, 0, 256); //Receive data from Shell printf("reading data from %d\n", FD_src); ReadMessage(FD_src, buffer); //Send data to CE printf("sending data to %d\n", FD_dest); SendMessage(FD_dest, buffer); FD_ZERO(&sockSet); FD_SET(FD_dest, &sockSet); selTimeout.tv_sec = 0; selTimeout.tv_usec = 50; //Check if there is a message on the CE socket ready to be processed rc=select(FD_dest + 1, &sockSet, NULL, NULL, &selTimeout); } memset(buffer, 0, 256); ReadMessage(FD_dest, buffer); printf("done transact data %s\n", buffer); } // Rules for active missions (currently) // -Three inputs/outputs per service and per mission // -Inputs simply define a path, so multiple variables can be transmitted over the same input // -Each component that takes input is responsible for sending an "ack" signal when transmission is complete // -Transmission will continue until the "ack" signal is recieved // -Any input from shell to a CE must be the first input // -CE-CE inputs must be listed in the order the ouptuts are generated // -No ability to store data locally at this time, so all CE's must be ready to receive data as soon as it is sent // -Shell should be ready for output in order that it is generated // -If/While supported and nesting too (except nested while loops) // -Conditions must be boolean flags // -Flags are set by putting either the character string "true" or "false" on the buffer // This function works by first sending the inputs from the shell to the appropriate components // The first service should begin immeadiately, as should any others who have all of their input paramaters // When they complete, the output path is found and the data is transfered as it becomes available // Presumably at this point the second function has all of it's paramaters, so it begins to compute, and the cycle repeats // If the generated output is an overall output, it is sent on to the shell // "if" and "while" statements are handled by setting up a faux service that has a true input, a false input, and a boolean flag // If the true input is non-NULL and the flag is true, the statements execute // Likewise, if the false input is non-NULL and the flag is false, the statements execute // These flags are set during execution any time one of these faux services' inputs appear in an output statement // void ServiceManagementLayer::PerformActiveMission() { int i = 0; char *buffer; if(!miss[activeMission].input[0].empty()){ printf("mission input 1 not empty\n"); for(int j = 0; j < miss[activeMission].numServices; j++) { if(miss[activeMission].services[j].input[0].compare(miss[activeMission].input[0]) == 0){ if(miss[activeMission].services[j].num_conds > 0){ memset(buffer, 0, 256); ReadMessage(shellSocketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } SendMessage(miss[activeMission].services[j].socketFD, "request_optimization_service"); SendMessage(miss[activeMission].services[j].socketFD, miss[activeMission].services[j].name.c_str()); TransactData(-1, miss[activeMission].services[j].componentID); } } } if(!miss[activeMission].input[1].empty()){ for(int j = 0; j < miss[activeMission].numServices; j++) { if(miss[activeMission].services[j].input[1].compare(miss[activeMission].input[0]) == 0){ if(miss[activeMission].services[j].num_conds > 0){ memset(buffer, 0, 256); ReadMessage(shellSocketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } SendMessage(miss[activeMission].services[j].socketFD, "request_optimization_service"); SendMessage(miss[activeMission].services[j].socketFD, miss[activeMission].services[j].name.c_str()); TransactData(-1, miss[activeMission].services[j].componentID); } if(miss[activeMission].services[j].input[1].compare(miss[activeMission].input[1]) == 0) TransactData(-1, miss[activeMission].services[j].componentID); } } if(!miss[activeMission].input[2].empty()){ for(int j = 0; j < miss[activeMission].numServices; j++) { if(miss[activeMission].services[j].input[2].compare(miss[activeMission].input[0]) == 0){ if(miss[activeMission].services[j].num_conds > 0){ memset(buffer, 0, 256); ReadMessage(shellSocketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } SendMessage(miss[activeMission].services[j].socketFD, "request_optimization_service"); SendMessage(miss[activeMission].services[j].socketFD, miss[activeMission].services[j].name.c_str()); TransactData(-1, miss[activeMission].services[j].componentID); } if(miss[activeMission].services[j].input[2].compare(miss[activeMission].input[1]) == 0) TransactData(-1, miss[activeMission].services[j].componentID); if(miss[activeMission].services[j].input[2].compare(miss[activeMission].input[2]) == 0) TransactData(-1, miss[activeMission].services[j].componentID); } } while(i != miss[activeMission].numServices) { if(miss[activeMission].services[i].name.compare("while")==0) { int32_t stmt_i = i; i+=miss[activeMission].services[stmt_i].num_conds; while((miss[activeMission].services[stmt_i].cond_flag && !miss[activeMission].services[stmt_i].input[0].empty()) ||\ (!miss[activeMission].services[stmt_i].cond_flag && !miss[activeMission].services[stmt_i].input[1].empty())){ for(int32_t k=stmt_i+1; k <= stmt_i+miss[activeMission].services[stmt_i].num_conds; k++){ if(strcmp(miss[activeMission].services[i].name.c_str(), "if")==0){ int32_t stmt_k = k; if((miss[activeMission].services[stmt_k].cond_flag && !miss[activeMission].services[stmt_k].input[0].empty()) ||\ (!miss[activeMission].services[stmt_k].cond_flag && !miss[activeMission].services[stmt_k].input[1].empty())){ for(int n = stmt_k+1; n <= stmt_k+miss[activeMission].services[stmt_k].num_conds; n++){ for(int m = 0; m < 3; m++){ for(int j = 0; j < 3; j++){ if(miss[activeMission].services[k].output[m].compare(miss[activeMission].output[j])==0 && \ !miss[activeMission].services[k].output[m].empty()){ TransactData(miss[activeMission].services[k].componentID, -1); break; } } for(int j = 0; j < miss[activeMission].numServices; j++){ if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[0]) == 0 && \ !miss[activeMission].services[k].output[m].empty()){ if(miss[activeMission].services[j].num_conds > 0){ memset(buffer, 0, 256); ReadMessage(miss[activeMission].services[k].socketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } SendMessage(miss[activeMission].services[j].socketFD, "request_optimization_service"); SendMessage(miss[activeMission].services[j].socketFD, miss[activeMission].services[j].name.c_str()); TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[1]) == 0 && \ !miss[activeMission].services[k].output[m].empty()){ if(miss[activeMission].services[j].num_conds > 0){ memset(buffer, 0, 256); ReadMessage(miss[activeMission].services[k].socketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[2]) == 0){ TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } } } } } } else{ for(int m = 0; m < 3; m++) { for(int j = 0; j < 3; j++){ if(miss[activeMission].services[k].output[m].compare(miss[activeMission].output[j])==0 && \ !miss[activeMission].services[k].output[m].empty()){ TransactData(miss[activeMission].services[k].componentID, -1); break; } } for(int j = 0; j < miss[activeMission].numServices; j++){ if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[0]) == 0 && \ !miss[activeMission].services[k].output[m].empty()){ if(miss[activeMission].services[j].num_conds > 0){ memset(buffer, 0, 256); ReadMessage(miss[activeMission].services[k].socketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } SendMessage(miss[activeMission].services[j].socketFD, "request_optimization_service"); SendMessage(miss[activeMission].services[j].socketFD, miss[activeMission].services[j].name.c_str()); TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[1]) == 0 && \ !miss[activeMission].services[k].output[m].empty()){ if(miss[activeMission].services[j].num_conds > 0){ memset(buffer, 0, 256); ReadMessage(miss[activeMission].services[k].socketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[2]) == 0 && \ !miss[activeMission].services[k].output[m].empty()){ TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } } } } } } } else if(miss[activeMission].services[i].name.compare("if")==0) { int32_t stmt_i = i; i+=miss[activeMission].services[stmt_i].num_conds; if((miss[activeMission].services[stmt_i].cond_flag && !miss[activeMission].services[stmt_i].input[0].empty()) ||\ (!miss[activeMission].services[stmt_i].cond_flag && !miss[activeMission].services[stmt_i].input[1].empty())){ for(int32_t k=stmt_i+1; k <= stmt_i+miss[activeMission].services[stmt_i].num_conds; k++){ if(strcmp(miss[activeMission].services[i].name.c_str(), "if")==0){ int32_t stmt_k = k; if((miss[activeMission].services[stmt_k].cond_flag && !miss[activeMission].services[stmt_k].input[0].empty()) ||\ (!miss[activeMission].services[stmt_k].cond_flag && !miss[activeMission].services[stmt_k].input[1].empty())){ for(int n = stmt_k+1; n <= stmt_k+miss[activeMission].services[stmt_k].num_conds; n++){ for(int m = 0; m < 3; m++) { for(int j = 0; j < 3; j++){ if(miss[activeMission].services[k].output[m].compare(miss[activeMission].output[j])==0 && \ !miss[activeMission].services[k].output[m].empty()){ TransactData(miss[activeMission].services[k].componentID, -1); break; } } for(int j = 0; j < miss[activeMission].numServices; j++){ if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[0]) == 0 && \ !miss[activeMission].services[k].output[m].empty()){ if(miss[activeMission].services[j].num_conds > 0){ memset(buffer, 0, 256); ReadMessage(miss[activeMission].services[k].socketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } SendMessage(miss[activeMission].services[j].socketFD, "request_optimization_service"); SendMessage(miss[activeMission].services[j].socketFD, miss[activeMission].services[j].name.c_str()); TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[1]) == 0 && \ !miss[activeMission].services[k].output[m].empty()){ if(miss[activeMission].services[j].num_conds > 0){ memset(buffer, 0, 256); ReadMessage(miss[activeMission].services[k].socketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[2]) == 0 && \ !miss[activeMission].services[k].output[m].empty()){ TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } } } } } } else{ for(int m = 0; m < 3; m++) { for(int j = 0; j < 3; j++){ if(miss[activeMission].services[k].output[m].compare(miss[activeMission].output[j])==0 && \ !miss[activeMission].services[k].output[m].empty()){ TransactData(miss[activeMission].services[k].componentID, -1); break; } } for(int j = 0; j < miss[activeMission].numServices; j++){ if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[0]) == 0 && \ !miss[activeMission].services[k].output[m].empty()){ if(miss[activeMission].services[j].num_conds > 0){ ReadMessage(miss[activeMission].services[k].socketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } SendMessage(miss[activeMission].services[j].socketFD, "request_optimization_service"); SendMessage(miss[activeMission].services[j].socketFD, miss[activeMission].services[j].name.c_str()); TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[1]) == 0 && \ !miss[activeMission].services[k].output[m].empty()){ if(miss[activeMission].services[j].num_conds > 0){ ReadMessage(miss[activeMission].services[k].socketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } if(miss[activeMission].services[k].output[m].compare(miss[activeMission].services[j].input[2]) == 0 && \ !miss[activeMission].services[k].output[m].empty()){ TransactData(miss[activeMission].services[k].componentID, miss[activeMission].services[j].componentID); break; } } } } } } } else{ for(int m = 0; m < 3; m++) { printf("\ninside SAM\n"); for(int j = 0; j < 3; j++){ if(miss[activeMission].services[i].output[m].compare(miss[activeMission].output[j])==0 && \ !miss[activeMission].services[i].output[m].empty()){ printf("i=%d, m=%d, j=%d\n", i, m, j); TransactData(miss[activeMission].services[i].componentID, -1); break; } } for(int j = 0; j < miss[activeMission].numServices; j++){ if(miss[activeMission].services[i].output[m].compare(miss[activeMission].services[j].input[0]) == 0 && \ !miss[activeMission].services[i].output[m].empty()){ if(miss[activeMission].services[j].num_conds > 0){ ReadMessage(miss[activeMission].services[i].socketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } SendMessage(miss[activeMission].services[j].socketFD, "request_optimization_service"); SendMessage(miss[activeMission].services[j].socketFD, miss[activeMission].services[j].name.c_str()); TransactData(miss[activeMission].services[i].componentID, miss[activeMission].services[j].componentID); break; } if(miss[activeMission].services[i].output[m].compare(miss[activeMission].services[j].input[1]) == 0 && \ !miss[activeMission].services[i].output[m].empty()){ if(miss[activeMission].services[j].num_conds > 0){ ReadMessage(miss[activeMission].services[i].socketFD, buffer); if(strcmp(buffer, "false")==0) miss[activeMission].services[j].cond_flag=false; else miss[activeMission].services[j].cond_flag=true; break; } TransactData(miss[activeMission].services[i].componentID, miss[activeMission].services[j].componentID); break; } if(miss[activeMission].services[i].output[m].compare(miss[activeMission].services[j].input[2]) == 0 && \ !miss[activeMission].services[i].output[m].empty()){ TransactData(miss[activeMission].services[i].componentID, miss[activeMission].services[j].componentID); break; } } } } i++; } } //Verified May 26 void ServiceManagementLayer::ListServices() { // generate commandi strcpy(_services_DB->command, "select "); strcat(_services_DB->command, _services_DB->tablename); strcat(_services_DB->command, ".* from "); strcat(_services_DB->command, _services_DB->tablename); strcat(_services_DB->command, ";"); // execute print (select all) command char *errorMsg; int rc = sqlite3_exec(_services_DB->db, _services_DB->command, callback, 0, &errorMsg); if( rc!=SQLITE_OK && rc!=101 ) fprintf(stderr, "SQL error: %s\n", errorMsg); printf("database %s, table %s:\n", _services_DB->filename, _services_DB->tablename); } void ServiceManagementLayer::ReloadConfiguration() { LOG("ServiceManagementLayer:: Reloading Configuration.\n"); free(miss); miss = new Mission[10]; for(int i = 0; i < 10; i++) miss[i].services = new Service[20]; LoadConfiguration(_SML_Config, miss); } //IMPORTANT - See formatting instructions for correct parsing of data //Can currently handle 3 inputs and 3 outputs per service, but easily expandable //Also, can handle one layer of nested conditional statements, but could //be expanded to meet additional needs. Only support now is for straight bool flags, //but support could be added for more complex conditionals later. //Components assigned to mission during "set active mission" stage so that //components can still continue to register after the configuration is loaded //Verified May 26 void ServiceManagementLayer::LoadConfiguration(const char *SML_Config, Mission* &mList) { TiXmlElement *pMission; TiXmlElement *pService; TiXmlElement *pChild0, *pChild1, *pChild2, *pChild3; TiXmlHandle hRoot(0); //printf("ServiceManagementLayer:: Loading Configuration.\n"); TiXmlDocument doc("."); doc.LoadFile(SML_Config); bool loadOkay = doc.LoadFile(); if(!loadOkay) printf("Loading SML configuration failed: %s\n", SML_Config); TiXmlHandle hDoc(&doc); pMission = hDoc.FirstChildElement().Element(); if(!pMission) printf("No valid root!"); hRoot = TiXmlHandle(pMission); pService = pMission->FirstChildElement(); int32_t mission_num = 0; //Iterate through the missions for(pChild0 = pMission->FirstChildElement(); pChild0 ; \ pChild0 = pChild0->NextSiblingElement()) { int32_t service_num = 0; uint16_t cond_array[] = {0, 0}; //printf("mission_num = %d\n", mission_num); memset(cond_array, 0, 2); for(pChild1 = pChild0->FirstChildElement(); pChild1; \ pChild1 = pChild1->NextSiblingElement()) { int32_t conditional_0 = service_num; for(pChild2 = pChild1->FirstChildElement(); \ pChild2; pChild2 = pChild2->NextSiblingElement()) { service_num++; int32_t conditional_1 = service_num; for(pChild3 = pChild2->FirstChildElement(); \ pChild3; pChild3 = pChild3 ->NextSiblingElement()) { service_num++; mList[mission_num].services[service_num].name = pChild3->Attribute("name"); if(pChild3->Attribute("input1")) mList[mission_num].services[service_num].input[0] = pChild3->Attribute("input1"); if(pChild3->Attribute("input2")) mList[mission_num].services[service_num].input[1] = pChild3->Attribute("input2"); if(pChild3->Attribute("input3")) mList[mission_num].services[service_num].input[2] = pChild3->Attribute("input3"); if(pChild3->Attribute("output1")) mList[mission_num].services[service_num].output[0] = pChild3->Attribute("output1"); if(pChild3->Attribute("output2")) mList[mission_num].services[service_num].output[1] = pChild3->Attribute("output2"); if(pChild3->Attribute("output3")) mList[mission_num].services[service_num].output[2] = pChild3->Attribute("output3"); cond_array[1]++; } if(conditional_1 != service_num){ mList[mission_num].services[conditional_1].name = pChild2->Value(); if(pChild2->Attribute("input_t")) mList[mission_num].services[service_num].input[0] = pChild2->Attribute("input_t"); if(pChild2->Attribute("input_f")) mList[mission_num].services[service_num].input[1] = pChild2->Attribute("input_f"); } else{ mList[mission_num].services[conditional_1].name = pChild2->Attribute("name"); if(pChild2->Attribute("input1")) mList[mission_num].services[service_num].input[0] = pChild2->Attribute("input1"); if(pChild2->Attribute("input2")) mList[mission_num].services[service_num].input[1] = pChild2->Attribute("input2"); if(pChild2->Attribute("input3")) mList[mission_num].services[service_num].input[2] = pChild2->Attribute("input3"); if(pChild2->Attribute("output1")) mList[mission_num].services[service_num].output[0] = pChild2->Attribute("output1"); if(pChild2->Attribute("output2")) mList[mission_num].services[service_num].output[1] = pChild2->Attribute("output2"); if(pChild2->Attribute("output3")) mList[mission_num].services[service_num].output[2] = pChild2->Attribute("output3"); } mList[mission_num].services[conditional_1].num_conds = cond_array[1]; cond_array[1] = 0; cond_array[0]++; } if(conditional_0 != service_num){ mList[mission_num].services[conditional_0].name = pChild1->Value(); if(pChild1->Attribute("input_t")) mList[mission_num].services[service_num].input[0] = pChild1->Attribute("input_t"); if(pChild1->Attribute("input_f")) mList[mission_num].services[service_num].input[1] = pChild1->Attribute("input_f");} else{ mList[mission_num].services[conditional_0].name = pChild1->Attribute("name"); if(pChild1->Attribute("input1")) mList[mission_num].services[service_num].input[0] = pChild1->Attribute("input1"); if(pChild1->Attribute("input2")) mList[mission_num].services[service_num].input[1] = pChild1->Attribute("input2"); if(pChild1->Attribute("input3")) mList[mission_num].services[service_num].input[2] = pChild1->Attribute("input3"); if(pChild1->Attribute("output1")) mList[mission_num].services[service_num].output[0] = pChild1->Attribute("output1"); if(pChild1->Attribute("output2")) mList[mission_num].services[service_num].output[1] = pChild1->Attribute("output2"); if(pChild1->Attribute("output3")) mList[mission_num].services[service_num].output[2] = pChild1->Attribute("output3"); } mList[mission_num].services[conditional_0].num_conds = cond_array[0]; //printf("hello\n"); cond_array[0] = 0; service_num++; } for(int i = 0; i < service_num; i++) printf("%d, input1=%s, output1=%s\n", i, mList[mission_num].services[i].input[0].c_str(), mList[mission_num].services[i].output[0].c_str()); mList[mission_num].numServices = service_num; mList[mission_num].name = pChild0->Attribute("name"); mList[mission_num].missionID = atoi(pChild0->Attribute("id")); if(pChild0->Attribute("input1")) mList[mission_num].input[0] = pChild0->Attribute("input1"); if(pChild0->Attribute("input2")) mList[mission_num].input[1] = pChild0->Attribute("input2"); if(pChild0->Attribute("input3")) mList[mission_num].input[2] = pChild0->Attribute("input3"); if(pChild0->Attribute("output1")) mList[mission_num].output[0] = pChild0->Attribute("output1"); if(pChild0->Attribute("output2")) mList[mission_num].output[1] = pChild0->Attribute("output2"); if(pChild0->Attribute("output3")) mList[mission_num].output[2] = pChild0->Attribute("output3"); printf("mis, input1=%s, output1=%s\n", mList[mission_num].input[0].c_str(), mList[mission_num].output[0].c_str()); mission_num++; } /*TiXmlElement *pMission; TiXmlElement *pService; TiXmlElement *pChild0, *pChild1, *pChild2, *pChild3; TiXmlHandle hRoot(0); //printf("ServiceManagementLayer:: Loading Configuration.\n"); TiXmlDocument doc("."); doc.LoadFile(SML_Config); bool loadOkay = doc.LoadFile(); if(!loadOkay) printf("Loading SML configuration failed: %s\n", SML_Config); TiXmlHandle hDoc(&doc); pMission = hDoc.FirstChildElement().Element(); if(!pMission) printf("No valid root!"); hRoot = TiXmlHandle(pMission); pService = pMission->FirstChildElement(); int32_t mission_num = 0; //Iterate through the missions for(pChild0 = pMission->FirstChildElement(); pChild0 ; \ pChild0 = pChild0->NextSiblingElement()) { int32_t service_num = 0; uint16_t cond_array[] = {0, 0}; //printf("mission_num = %d\n", mission_num); memset(cond_array, 0, 2); for(pChild1 = pChild0->FirstChildElement(); pChild1; \ pChild1 = pChild1->NextSiblingElement()) { int32_t conditional_0 = service_num; for(pChild2 = pChild1->FirstChildElement(); \ pChild2; pChild2 = pChild2->NextSiblingElement()) { service_num++; int32_t conditional_1 = service_num; for(pChild3 = pChild2->FirstChildElement(); \ pChild3; pChild3 = pChild3 ->NextSiblingElement()) { service_num++; mList[mission_num].services[service_num].name = pChild3->Attribute("name"); if(pChild3->Attribute("input1")) mList[mission_num].services[service_num].input[0] = pChild3->Attribute("input1"); if(pChild3->Attribute("input2")) mList[mission_num].services[service_num].input[1] = pChild3->Attribute("input2"); if(pChild3->Attribute("input3")) mList[mission_num].services[service_num].input[2] = pChild3->Attribute("input3"); if(pChild3->Attribute("output1")) mList[mission_num].services[service_num].output[0] = pChild3->Attribute("output1"); if(pChild3->Attribute("output2")) mList[mission_num].services[service_num].output[1] = pChild3->Attribute("output2"); if(pChild3->Attribute("output3")) mList[mission_num].services[service_num].output[2] = pChild3->Attribute("output3"); cond_array[1]++; } if(conditional_1 != service_num){ mList[mission_num].services[conditional_1].name = pChild2->Value(); if(pChild2->Attribute("input_t")) mList[mission_num].services[conditional_1].input[0] = pChild2->Attribute("input_t"); if(pChild2->Attribute("input_f")) mList[mission_num].services[conditional_1].input[1] = pChild2->Attribute("input_f"); } else{ mList[mission_num].services[service_num].name = pChild2->Attribute("name"); if(pChild2->Attribute("input1")) mList[mission_num].services[service_num].input[0] = pChild2->Attribute("input1"); if(pChild2->Attribute("input2")) mList[mission_num].services[service_num].input[1] = pChild2->Attribute("input2"); if(pChild2->Attribute("input3")) mList[mission_num].services[service_num].input[2] = pChild2->Attribute("input3"); if(pChild2->Attribute("output1")) mList[mission_num].services[service_num].output[0] = pChild2->Attribute("output1"); if(pChild2->Attribute("output2")) mList[mission_num].services[service_num].output[1] = pChild2->Attribute("output2"); if(pChild2->Attribute("output3")) mList[mission_num].services[service_num].output[2] = pChild2->Attribute("output3"); } mList[mission_num].services[conditional_1].num_conds = cond_array[1]; cond_array[1] = 0; cond_array[0]++; } if(conditional_0 != service_num){ mList[mission_num].services[conditional_0].name = pChild1->Value(); if(pChild1->Attribute("input_t")) mList[mission_num].services[conditional_0].input[0] = pChild1->Attribute("input_t"); if(pChild1->Attribute("input_f")) mList[mission_num].services[conditional_0].input[1] = pChild1->Attribute("input_f"); printf("if detected %s, %s\n", pChild1->Attribute("input_f"), pChild1->Attribute("input_t")); } else{ mList[mission_num].services[service_num].name = pChild1->Attribute("name"); if(pChild1->Attribute("input1")) mList[mission_num].services[service_num].input[0] = pChild1->Attribute("input1"); if(pChild1->Attribute("input2")) mList[mission_num].services[service_num].input[1] = pChild1->Attribute("input2"); if(pChild1->Attribute("input3")) mList[mission_num].services[service_num].input[2] = pChild1->Attribute("input3"); if(pChild1->Attribute("output1")) mList[mission_num].services[service_num].output[0] = pChild1->Attribute("output1"); if(pChild1->Attribute("output2")) mList[mission_num].services[service_num].output[1] = pChild1->Attribute("output2"); if(pChild1->Attribute("output3")) mList[mission_num].services[service_num].output[2] = pChild1->Attribute("output3"); } mList[mission_num].services[conditional_0].num_conds = cond_array[0]; //printf("hello\n"); cond_array[0] = 0; service_num++; } for(int i = 0; i < service_num; i++) printf("input1=%s, output1=%s\n", mList[mission_num].services[i].input[0].c_str(), mList[mission_num].services[service_num].output[0].c_str()); mList[mission_num].numServices = service_num; mList[mission_num].name = pChild0->Attribute("name"); mList[mission_num].missionID = atoi(pChild0->Attribute("id")); if(pChild0->Attribute("input1")) mList[mission_num].input[0] = pChild0->Attribute("input1"); if(pChild0->Attribute("input2")) mList[mission_num].input[1] = pChild0->Attribute("input2"); if(pChild0->Attribute("input3")) mList[mission_num].input[2] = pChild0->Attribute("input3"); if(pChild0->Attribute("output1")) mList[mission_num].output[0] = pChild0->Attribute("output1"); if(pChild0->Attribute("output2")) mList[mission_num].output[1] = pChild0->Attribute("output2"); if(pChild0->Attribute("output3")) mList[mission_num].output[2] = pChild0->Attribute("output3"); printf("input1=%s, outpu1=%s\n", mList[mission_num].input[0].c_str(), mList[mission_num].output[0].c_str()); mission_num++; }*/ } //Verified w/o Transfers May 26 void ServiceManagementLayer::RegisterCognitiveEngine(int32_t ID) { SendMessage(shellSocketFD, "register_engine_cognitive"); LOG("ServiceManagementLayer:: CE registration message forwarded to shell.\n"); //printf("ServiceManagementLayer:: CE registration message forwarded to shell.\n"); //TransferRadioConfiguration(ID); //TransferExperience(ID); numberOfCognitiveEngines++; CE_Present = true; } void ServiceManagementLayer::DeregisterServices(int32_t ID) { char str_buffer[64]; strcpy(_services_DB->command, "delete "); strcat(_services_DB->command, _services_DB->tablename); strcat(_services_DB->command, ".* from "); strcat(_services_DB->command, _services_DB->tablename); strcat(_services_DB->command, " where "); strcat(_services_DB->command, "ID_Num"); strcat(_services_DB->command, "=="); sprintf(str_buffer, "%d;", ID); strcat(_services_DB->command, str_buffer); sqlite3_exec(_services_DB->db, _services_DB->command, NULL, 0, NULL); } void ServiceManagementLayer::DeregisterCognitiveEngine(int32_t ID) { LOG("ServiceManagementLayer:: CE deregistration message forwarded to shell.\n"); numberOfCognitiveEngines--; if(numberOfCognitiveEngines == 0) CE_Present = false; SendMessage(shellSocketFD, "deregister_engine_cognitive"); char buffer[256]; memset(buffer, 0, 256); ReadMessage(shellSocketFD, buffer); SendMessage(CE_List[ID].FD, buffer); if(strcmp("deregister_ack", buffer) != 0) { ERROR(1, "SML:: Failed to close CE socket\n"); } CE_List[ID].FD = -1; CE_List[ID].ID_num = -1; LOG("Cognitive Radio Shell:: Socket closed.\n"); } //VERIFIED May 21 void ServiceManagementLayer::StartSMLServer() { struct timeval selTimeout; int32_t running = 1; int32_t port, rc, new_sd = 1; int32_t desc_ready = 1; int32_t timeout = 10; //If there is, call the MessageHandler with the Shell_Msg code of -1 fd_set sockSet, shellSet; cogEngSrv = CreateTCPServerSocket(2036); int32_t maxDescriptor = cogEngSrv; if(InitializeTCPServerPort(cogEngSrv) == -1) ERROR(1,"Error initializing primary port\n"); /*int FD = ClientSocket("127.0.0.1", "2013"); SendMessage(FD, "register_engine_cognitive"); SendMessage(FD, "register_service"); SendMessage(FD, "test_srv"); SendMessage(FD, "list_services"); int FD2 = ClientSocket("127.0.0.1", "2013"); SendMessage(FD2, "register_engine_cognitive"); SendMessage(FD2, "register_service"); SendMessage(FD2, "test_srv1"); SendMessage(FD2, "list_services");*/ //SendMessage(shellSocketFD, "list_services");*/ //printf("num = %d, %d, %d\n", one, two, three); int i = 10000000; while (i>0) { i--; /* Zero socket descriptor vector and set for server sockets */ /* This must be reset every time select() is called */ FD_ZERO(&sockSet); FD_SET(cogEngSrv, &sockSet); for(int k = 0; k < Current_ID; k++) FD_SET(CE_List[k].FD, &sockSet); //printf("k=%d, CID=%d\n", k, CE_List[k].FD); /* Timeout specification */ /* This must be reset every time select() is called */ selTimeout.tv_sec = 0; /* timeout (secs.) */ selTimeout.tv_usec = 0; /* 0 microseconds */ //Changed both to zero so that select will check messages from the shell instead of blocking //when there is no command from the CE's to be processed //Check if there is a message on the socket waiting to be read rc = select(maxDescriptor + 1, &sockSet, NULL, NULL, &selTimeout); //printf("rc=%d\n", rc); if(rc == 0){ //LOG("No echo requests for %i secs...Server still alive\n", timeout); FD_ZERO(&shellSet); FD_SET(shellSocketFD, &shellSet); selTimeout.tv_sec = 0; selTimeout.tv_usec = 0; //Check if there is a message on the shell socket ready to be processed int rc2 = select(shellSocketFD + 1, &shellSet, NULL, NULL, &selTimeout); //printf("rc2=%d\n", rc2); //If there is, call the MessageHandler with the Shell_Msg code of -1 if(FD_ISSET(shellSocketFD, &shellSet)){ //printf("shell_msg, %d\n", rc2); MessageHandler(-1);} } else { desc_ready = rc; for(port = 0; port <= maxDescriptor && desc_ready > 0; port++) { if(FD_ISSET(port, &sockSet)) { desc_ready -= 1; //Check if request is new or on an existing open descriptor if(port == cogEngSrv) { //printf("here1\n"); // do { new_sd = AcceptTCPConnection(port); //printf("sd = %d\n", new_sd); if(new_sd < 0) break; //Set not to block /*int oldflags = fcntl (new_sd, F_GETFL, 0); oldflags |= O_NONBLOCK; fcntl (new_sd, F_SETFL, oldflags);*/ CE_List[Current_ID].FD = new_sd; CE_List[Current_ID].ID_num = Current_ID; MessageHandler(Current_ID); Current_ID++; FD_SET(new_sd,&sockSet); if(new_sd > maxDescriptor) maxDescriptor = new_sd; //LOG("New incoming connection - %i\n\n",new_sd); // } while(new_sd != -1); } else { //printf("here2\n"); //LOG("Request on already open descriptor.\n\n"); for(int16_t z = 0; z < Current_ID; z++) { if(CE_List[z].FD == port){ //printf("z=%d\n", z); MessageHandler(z);} } } } } } } /* Close sockets */ close(cogEngSrv); //delete &cogEngSrv; return; }