root/vtcross/trunk/src/service_management_layer/ServiceManagementLayer.cpp @ 442

Revision 442, 69.2 KB (checked in by bhilburn, 15 years ago)

Fixed a memory leak (and redundant memory allocation), and moved the
internal storage of SML_Config to a std::string to prevent a segfault.

Line 
1/*
2 Copyright 2009 Virginia Polytechnic Institute and State University 
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7 
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/* Inter-component communication handled by sockets and FD's. 
18 * Server support has been completely implemented and tested.
19 *
20 * Services are stored in a SQLite DB by the ID of the CE that registered them.  Service
21 * support has been completely implemented and tested.
22 *
23 * Missions are loaded from an XML file, connected with services provided by components,
24 * and run.  See the documentation for the "PerformActiveMission" below for important
25 * info.
26 */
27
28
29#include <cmath>
30#include <cstdio>
31#include <cstdlib>
32#include <cstring>
33#include <stdint.h>
34
35#include <arpa/inet.h>
36#include <iostream>
37#include <netinet/in.h>
38#include <netdb.h>
39#include <fcntl.h>
40#include <sqlite3.h>
41#include <string>
42#include <sys/ioctl.h>
43#include <sys/mman.h>
44#include <sys/socket.h>
45#include <sys/types.h>
46#include <sys/wait.h>
47
48#include "tinyxml/tinyxml.h"
49#include "tinyxml/tinystr.h"
50
51#include "vtcross/debug.h"
52#include "vtcross/error.h"
53#include "vtcross/common.h"
54#include "vtcross/components.h"
55#include "vtcross/containers.h"
56#include "vtcross/socketcomm.h"
57
58
59typedef struct services_s *services_DB;
60typedef struct data_s *data_DB;
61
62using namespace std;
63
64struct services_s {
65    string filename;
66    string tablename;
67    string command;
68    sqlite3 *db;
69    unsigned int num_columns;
70};
71
72struct data_s {
73    string filename;
74    string tablename;
75    string command;
76    sqlite3 *db;
77    unsigned int num_columns;
78};
79
80services_DB _services_DB;
81data_DB _data_DB;
82string _SML_Config;
83bool shellFound;
84
85/* Callback function used internally by some of the SQLite3 commands */
86int32_t
87callback(void *notUsed, int32_t argc, char **argv, char **azColName)
88{
89    for(size_t i = 0; i < argc; i++) {
90        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
91    }
92
93    printf("\n");
94    return 0;
95}
96
97ServiceManagementLayer::ServiceManagementLayer()
98{
99    LOG("Creating Service Management Layer.\n");
100
101    shellSocketFD = -1;
102    numberOfCognitiveEngines = 0;
103    CE_Present = false;
104    cogEngSrv = 1;
105}
106
107/* Free and clear the DB's associated with this SML in the destructor.
108 *
109 * Note that exiting with an error condition will cause SML to not be destructed,
110 * resulting in the DB's staying in memory until the destructor is encountered in
111 * future executions. */
112ServiceManagementLayer::~ServiceManagementLayer()
113{
114    char *errorMsg;
115    int32_t rc;         /* sqlite command return code */
116
117    _services_DB->command="drop table ";
118    _services_DB->command.append(_services_DB->tablename);
119    rc = sqlite3_exec(_services_DB->db, _services_DB->command.c_str(), callback, 0, &errorMsg);
120    if((rc != SQLITE_OK) && (rc != 101))
121        WARNING("ServiceManagementLayer::Destructor services 'drop table' error: %s\n", errorMsg);
122
123    _services_DB->command="vacuum";
124    rc = sqlite3_exec(_services_DB->db, _services_DB->command.c_str(), callback, 0, &errorMsg);
125    if((rc != SQLITE_OK) && (rc != 101))
126        WARNING("ServiceManagementLayer::Destructor services 'vacuum' error: %s\n", errorMsg);
127
128    free(_services_DB);
129
130    _data_DB->command="drop table ";
131    _data_DB->command.append(_data_DB->tablename);
132    rc = sqlite3_exec(_data_DB->db, _data_DB->command.c_str(), callback, 0, &errorMsg);
133    if((rc != SQLITE_OK) && (rc != 101))
134        WARNING("ServiceManagementLayer::Destructor data 'drop table' error: %s\n", errorMsg);
135
136    _data_DB->command="vacuum";
137    rc = sqlite3_exec(_data_DB->db, _data_DB->command.c_str(), callback, 0, &errorMsg);
138    if((rc != SQLITE_OK) && (rc != 101))
139        WARNING("ServiceManagementLayer::Destructor data 'vacuum' error: %s\n", errorMsg);
140
141    free(_data_DB);
142}
143
144/* Note that sizes of CE_List, miss, and service are hardcoded for now.
145 * Also, their sizes are hardcoded into the code in various places; a fix
146 * for a future version. */
147ServiceManagementLayer::ServiceManagementLayer(const char* SML_Config, \
148    const char* serverName, const char* serverPort, int16_t clientPort)
149{
150    LOG("Creating Service Management Layer.\n");
151
152    _SML_Config = string(SML_Config);
153    SMLport = clientPort;
154
155    ConnectToShell(serverName, serverPort);
156    CE_List = new CE_Reg[10];
157
158    miss = new Mission[10];
159    for(size_t i = 0; i < 10; i++)
160        miss[i].services = new Service[30];
161
162    Current_ID = 0;
163
164    LoadConfiguration(SML_Config, miss);
165
166    CreateServicesDB();
167    CreateDataDB();
168}
169
170/* CALLED BY: constructor
171 * INPUTS: <none>
172 * OUTPUTS: <none>
173 *
174 * DESCRIPTION: Create and initialize a DB to hold the services registered by components
175 */
176void
177ServiceManagementLayer::CreateServicesDB()
178{
179    sqlite3_stmt *ppStmt;  /* OUT: Statement handle */
180    const char *pzTail;     /* OUT: Pointer to unused portion of zSql */
181
182    //_services_DB = (services_DB) malloc(sizeof(struct services_s));
183    _services_DB = new services_s;
184    // copy filename
185    _services_DB->filename="Services_Table";
186    // execute create database command
187    // database handle
188    //_services_DB->db = NULL;
189    sqlite3_open(_services_DB->filename.c_str(), &(_services_DB->db));
190    char* cols[] = {(char *)"ID_Num", (char *)"Service_Name"};
191
192
193    // copy tablename
194    _services_DB->tablename="Services";
195
196    //If program execution ends in anything other than a ordered shutdown, DB's will still be there for next run
197    //Need to get rid of it so that old data isn't inadvertantly used in the next execution cycle
198    _services_DB->command = "DROP TABLE IF EXISTS Services;";     
199
200    int rc = sqlite3_prepare_v2(_services_DB->db, _services_DB->command.c_str(), 128, &ppStmt, &pzTail);
201    if( rc!=SQLITE_OK && rc!=101 )
202        printf("ServiceManagementLayer::CreateServicesDB 'prepare_stmt' error %d\n", rc);
203    rc = sqlite3_step(ppStmt);
204    if( rc!=SQLITE_OK && rc!=101 )
205        printf("ServiceManagementLayer::CreateServicesDB 'step' error\n");
206
207    // number of columns in the table
208    _services_DB->num_columns = 2;
209
210    // generate command
211    _services_DB->command="CREATE TABLE ";
212    _services_DB->command.append(_services_DB->tablename);
213    _services_DB->command.append("(");
214    _services_DB->command.append(cols[0]);
215    _services_DB->command.append(" INT, ");
216    _services_DB->command.append(cols[1]);
217    _services_DB->command.append(" TEXT);");
218
219    // execute create table command
220
221    rc = sqlite3_prepare_v2(_services_DB->db, _services_DB->command.c_str(), 128, &ppStmt, &pzTail);
222    if( rc!=SQLITE_OK && rc!=101 )
223        printf("ServiceManagementLayer::CreateServicesDB 'prepare_stmt' error %d\n", rc);
224    rc = sqlite3_step(ppStmt);
225    if( rc!=SQLITE_OK && rc!=101 )
226        printf("ServiceManagementLayer::CreateServicesDB 'step' error\n");
227}
228
229/* CALLED BY: constructor
230 * INPUTS: <none>
231 * OUTPUTS: <none>
232 *
233 * DESCRIPTION: Create and initialize a DB to hold the data sent by components
234 */
235void
236ServiceManagementLayer::CreateDataDB()
237{
238    sqlite3_stmt *ppStmt;  /* OUT: Statement handle */
239    const char *pzTail;     /* OUT: Pointer to unused portion of zSql */
240
241    _data_DB = new data_s;//(data_DB) malloc(sizeof(struct data_s));
242
243    // create database
244
245    // copy filename
246    _data_DB->filename="Data_Table";
247    // execute create database command
248    // database handle
249    //_services_DB->db = NULL;
250    sqlite3_open(_data_DB->filename.c_str(), &(_data_DB->db));
251    char* cols[] = {(char *)"Tag", (char *)"Data"};
252
253    // create table
254
255    // copy tablename
256    _data_DB->tablename="Data";
257    _data_DB->command="DROP TABLE IF EXISTS Data;";     
258
259    int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), 128, &ppStmt, &pzTail);
260    if( rc!=SQLITE_OK && rc!=101 )
261        printf("ServiceManagementLayer::CreateServicesDB 'prepare_stmt' error %d\n", rc);
262    rc = sqlite3_step(ppStmt);
263    if( rc!=SQLITE_OK && rc!=101 )
264        printf("ServiceManagementLayer::CreateServicesDB 'step' error\n");
265
266
267    // number of columns in the table
268    _data_DB->num_columns = 2;
269
270    // generate command
271    _data_DB->command="CREATE TABLE ";
272    _data_DB->command.append(_data_DB->tablename);
273    _data_DB->command.append("(");
274    _data_DB->command.append(cols[0]);
275    //First column is the name of the data (coresponding to the name of the output/input pair)
276    //It is the primary key so any subsequent data with the same name will replace the row
277    _data_DB->command.append(" TEXT PRIMARY KEY ON CONFLICT REPLACE, ");
278    _data_DB->command.append(cols[1]);
279    _data_DB->command.append(" TEXT);");
280
281    // execute create table command
282
283    rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), 128, &ppStmt, &pzTail);
284    if( rc!=SQLITE_OK && rc!=101 )
285        printf("ServiceManagementLayer::CreateDataDB 'prepare_stmt' error %d\n", rc);
286    rc = sqlite3_step(ppStmt);
287    if( rc!=SQLITE_OK && rc!=101 )
288        printf("ServiceManagementLayer::CreateDataDB 'step' error\n");
289}
290
291/* CALLED BY: MessageHandler
292 * INPUTS: <none>
293 * OUTPUTS: <none>
294 *
295 * DESCRIPTION: Sends a message identifying this component as an SML to the Shell
296 */
297void
298ServiceManagementLayer::SendComponentType()
299{
300    SendMessage(shellSocketFD, "response_sml");
301    LOG("SML responded to GetRemoteComponentType query.\n");
302}
303
304/* CALLED BY: constructor
305 * INPUTS: |serverName| the IPv4 name of the server (127.0.0.1 for localhost)
306 *       |serverPort| the port on the server to connect to
307 * OUTPUTS: <none>
308 *
309 * DESCRIPTION: Connecting to the shell takes 2 steps
310 * 1) Establish a client socket for communication
311 * 2) Run the initial Registration/handshake routine
312 */
313void
314ServiceManagementLayer::ConnectToShell(const char* serverName, \
315        const char* serverPort)
316{
317    shellSocketFD = ClientSocket(serverName, serverPort);
318    RegisterComponent();
319}
320
321/* CALLED BY: StartSMLServer
322 * INPUTS: |ID| The ID number of the CE that has a message wating
323 * OUTPUTS: <none>
324 *
325 * DESCRIPTION: Called whenever a socket is identified as being ready for communication
326 *              This funciton reads the message and calls the appropriate helper
327 */
328void
329ServiceManagementLayer::MessageHandler(int32_t ID)
330{
331    char buffer[256];   
332    memset(buffer, 0, 256); 
333    int32_t _FD; 
334   
335    if(ID != -1)
336    _FD = CE_List[ID].FD;
337    else
338    _FD = shellSocketFD;
339    ReadMessage(_FD, buffer);
340    //printf("MH_buffer = %s\n", buffer);
341   
342    //--------Policy Engine Stuff - no policy engine support in this version-------//
343
344    //printf("********* %s **********\n", buffer);
345    // TODO
346    // If we send integer op codes rather than strings, this process will be
347    // MUCH faster since instead of donig string compares we can simply
348    // switch on the integer value...
349    /*if(strcmp(buffer, "register_service") == 0) {
350        if(strcmp(buffer, "policy_geo") == 0) {
351        }
352        else if(strcmp(buffer, "policy_time") == 0) {
353        }
354        else if(strcmp(buffer, "policy_spectrum") == 0) {
355        }
356        else if(strcmp(buffer, "policy_spacial") == 0) {
357        }
358    }
359    else if(strcmp(buffer, "deregister_service") == 0) {
360        if(strcmp(buffer, "policy_geo") == 0) {
361        }
362        else if(strcmp(buffer, "policy_time") == 0) {
363        }
364        else if(strcmp(buffer, "policy_spectrum") == 0) {
365        }
366        else if(strcmp(buffer, "policy_spacial") == 0) {
367        }
368    }*/
369
370    //Go down the list to call the appropriate function
371    if(strcmp(buffer, "query_component_type") == 0) {
372        SendComponentType();
373    }
374    else if(strcmp(buffer, "reset_sml") == 0) {
375        Reset();
376    }
377    else if(strcmp(buffer, "shutdown_sml") == 0) {
378        Shutdown();
379    }
380    else if(strcmp(buffer, "register_engine_cognitive") == 0) {
381         RegisterCognitiveEngine(ID);
382    }
383    else if(strcmp(buffer, "register_service") == 0) {
384     ReceiveServices(ID);
385    }
386    else if(strcmp(buffer, "send_component_type") == 0) {
387     SendComponentType();
388    }
389    else if(strcmp(buffer, "list_services") == 0) {
390     ListServices();
391    }
392    else if(strcmp(buffer, "set_active_mission") == 0) {
393    SetActiveMission();
394    }
395    else if(strcmp(buffer, "request_optimization") == 0) {
396    PerformActiveMission();
397    }
398    else if(strcmp(buffer, "deregister_engine_cognitive") == 0) {
399    DeregisterCognitiveEngine(ID);
400    }
401    else if(strcmp(buffer, "deregister_service") == 0) {
402    DeregisterServices(ID);
403    }
404}
405
406//TODO Finish
407/* CALLED BY: MessageHandler
408 * INPUTS: <none>
409 * OUTPUTS: <none>
410 *
411 * DESCRIPTION: Deregisters the component from the Shell.
412 */
413void
414ServiceManagementLayer::Shutdown()
415{
416    DeregisterComponent();
417}
418
419//TODO Finish
420/* CALLED BY: MessageHandler
421 * INPUTS: <none>
422 * OUTPUTS: <none>
423 *
424 * DESCRIPTION: Deregisters the component from the Shell
425 */
426void
427ServiceManagementLayer::Reset()
428{
429    DeregisterComponent();
430    ReloadConfiguration();
431}
432
433/* CALLED BY: ConnectToShell
434 * INPUTS: <none>
435 * OUTPUTS: <none>
436 *
437 * DESCRIPTION: Sends the registration message to the Shell
438 */
439void
440ServiceManagementLayer::RegisterComponent()
441{
442    SendMessage(shellSocketFD, "register_sml");
443    LOG("ServiceManagementLayer:: Registration message sent.\n");
444    //printf("SSFD = %d\n", shellSocketFD);
445}
446
447/* CALLED BY: Shutdown
448 * INPUTS: <none>
449 * OUTPUTS: <none>
450 *
451 * DESCRIPTION: Closes the client socket with the shell, sends a deregstration message
452 */
453void
454ServiceManagementLayer::DeregisterComponent()
455{
456    SendMessage(shellSocketFD, "deregister_sml");
457    LOG("ServiceManagementLayer:: Deregistration message sent.\n");
458
459    shutdown(shellSocketFD, 2);
460    close(shellSocketFD);
461    shellSocketFD = -1;
462    LOG("ServiceManagementLayer:: Shell socket closed.\n");
463}
464
465
466/* CALLED BY: RegisterCognitiveEngine
467 * INPUTS: |ID| The ID number of the component where the data is to be transfered to
468 * OUTPUTS: <none>
469 *
470 * DESCRIPTION: Streams config data directly from the shell to the CE, and checks
471 * for an "ack" message from the CE after every sent message
472 * to know when to stop communication.
473 */
474
475//Modified to check the incoming message buffer rather than the outgoing message buffer to avoid a portion of the delay
476//May change this again to handle data more inteligently, taking advantage of it's properties.
477void
478ServiceManagementLayer::TransferRadioConfiguration(int32_t ID)
479{
480    //printf("transRadConfig\n");
481    struct timeval selTimeout;
482    fd_set sockSet;
483    int32_t rc = 1;
484    char buffer[256];
485    //Send data until the CE sends an ACK message back
486    while(rc!=0){
487        memset(buffer, 0, 256);
488    //Receive data from Shell
489    ReadMessage(shellSocketFD, buffer);
490    //printf("buffer = %s\n", buffer);
491    //Send data to CE
492    SendMessage(CE_List[ID].FD, buffer);
493        FD_ZERO(&sockSet);
494        FD_SET(shellSocketFD, &sockSet);
495        selTimeout.tv_sec = 0;
496        selTimeout.tv_usec = 5000;
497        //Check if there is a message on the shell ready to be processed
498        rc=select(shellSocketFD + 1, &sockSet, NULL, NULL, &selTimeout);
499    }
500    memset(buffer, 0, 256);
501    ReadMessage(CE_List[ID].FD, buffer);
502    SendMessage(shellSocketFD, buffer);
503    //printf("transfer done!\n");
504}
505
506
507/* CALLED BY: RegisterCognitiveEngine
508 * INPUTS: |ID| The ID number of the component where the data is to be transfered to
509 * OUTPUTS: <none>
510 *
511 * DESCRIPTION: Simmilar to TransferRadioConfig, just with Experience data
512 */
513
514//Modified to check the incoming message buffer rather than the outgoing message buffer to avoid a portion of the delay
515//May change this again to handle data more inteligently, taking advantage of it's properties.
516void
517ServiceManagementLayer::TransferExperience(int32_t ID)
518{
519    struct timeval selTimeout;
520    fd_set sockSet;
521    int32_t rc = 1;
522    char buffer[256];
523    //Send data until the CE sends an ACK message back
524    while(rc!=0){
525    //printf("transfering...\n");
526        memset(buffer, 0, 256);
527    //Receive data from Shell
528    ReadMessage(shellSocketFD, buffer);
529    //printf("buffer = %s\n", buffer);
530    //Send data to CE
531    SendMessage(CE_List[ID].FD, buffer);
532        FD_ZERO(&sockSet);
533        FD_SET(shellSocketFD, &sockSet);
534        selTimeout.tv_sec = 0;
535        selTimeout.tv_usec = 5000;
536        //Check if there is a message on the shell ready to be processed
537        rc=select(shellSocketFD + 1, &sockSet, NULL, NULL, &selTimeout);
538    }
539    memset(buffer, 0, 256);
540    //printf("done trans exp!\n");
541    ReadMessage(CE_List[ID].FD, buffer);
542    SendMessage(shellSocketFD, buffer);
543}
544
545/* CALLED BY: MessageHandler
546 * INPUTS: |ID| The ID number of the component where service is located
547 * OUTPUTS: <none>
548 *
549 * DESCRIPTION: Inserts a service into the DB with the ID of the component where it exists
550 */
551void
552ServiceManagementLayer::ReceiveServices(int32_t ID)
553{
554    char buffer[256];
555    memset(buffer, 0, 256);
556    ReadMessage(CE_List[ID].FD, buffer);
557    char* cols[] = {(char *)"ID_Num", (char *)"Service_Name"};
558    //printf("RS_buffer = %s\n", buffer);
559    // generate command
560    _services_DB->command="insert into ";
561    _services_DB->command.append(_services_DB->tablename);
562    _services_DB->command.append(" (");
563    _services_DB->command.append(cols[0]);
564    _services_DB->command.append(", ");
565    _services_DB->command.append(cols[1]);
566    _services_DB->command.append(") ");
567    _services_DB->command.append(" values(");
568    char temp[3];
569    memset(temp,0,3);
570    sprintf(temp, "%d", ID);
571    _services_DB->command.append(temp);
572    _services_DB->command.append(", '");
573    _services_DB->command.append(buffer);
574    _services_DB->command.append("');");
575   
576    //printf("search command: %s\n", _services_DB->command);
577    // execute add command
578    char *errorMsg;
579    int rc = sqlite3_exec(_services_DB->db, _services_DB->command.c_str(), callback, 0, &errorMsg);
580    if( rc!=SQLITE_OK && rc!=101 )
581        fprintf(stderr, "ServiceManagementLayer::RecieveServices DB Error %s\n", errorMsg);
582    /*sprintf(outBuffer, "SML: Registering service '%s' from component number '%d'", buffer, ID);
583    LOG(outBuffer);*/
584}
585
586/* CALLED BY: MessageHandler
587 * INPUTS: <none>
588 * OUTPUTS: <none>
589 *
590 * DESCRIPTION: This method associates the services that components provide with the services that are requested in the mission
591 * Each service in the mission is given the ID and FD of a component that has registered to provide that service
592 * Deregistration is okay until this method is called without a reload, but if deregistration occurs after this
593 * method is called it needs to be called again even if other engines also provide the services
594 */
595void
596ServiceManagementLayer::SetActiveMission()
597{
598    char buffer[256];
599    memset(buffer, 0, 256);
600    ReadMessage(shellSocketFD, buffer);
601    uint32_t missID = atoi(buffer);
602    for(activeMission = 0; activeMission < 10; activeMission++)
603    {
604    //Find the active mission by comparing mission ID's
605    if(miss[activeMission].missionID == missID)
606        break;
607    }
608
609    LOG("ServiceManagementLayer:: Received Set Active Mission command: %i.\n",missID);
610    //For each service in the mission
611    for(uint16_t i = 0; i < miss[activeMission].numServices; i++)
612    {   
613    //Check whether the current service is an actual service or a conditional
614    if(miss[activeMission].services[i].name.compare("if") && miss[activeMission].services[i].name.compare("dowhile") && \
615       miss[activeMission].services[i].name.compare("shell")){
616        //If it is a service, search the database of registered services to find the ID of the component that registered it
617            _services_DB->command="select ";
618           _services_DB->command.append(_services_DB->tablename);
619            _services_DB->command.append(".* from ");
620            _services_DB->command.append( _services_DB->tablename);
621            _services_DB->command.append(" where Service_Name=='");
622        _services_DB->command.append(miss[activeMission].services[i].name);
623        _services_DB->command.append("';");
624   
625            sqlite3_stmt * pStatement;
626            int rc = sqlite3_prepare_v2(_services_DB->db, _services_DB->command.c_str(), -1, &pStatement, NULL);
627            if (rc == SQLITE_OK){
628                if (sqlite3_step(pStatement) == SQLITE_ROW)
629                 miss[activeMission].services[i].componentID =  sqlite3_column_int(pStatement, 0);
630                else {
631                printf("services_DB:: Mission requires service %s not provided by any connected component.\n",miss[activeMission].services[i].name.c_str());
632            rc=31337;
633            }
634             } else {
635            printf("services_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_services_DB->command.c_str());
636            }
637        //printf("s_name=%s\n",miss[activeMission].services[i].name.c_str());
638            sqlite3_finalize(pStatement);
639        miss[activeMission].services[i].socketFD = CE_List[miss[activeMission].services[i].componentID].FD;
640        //Set the FD and ID of the service to refer to the component where the service exists
641    }
642    //Nothing to be done for conditionals at this stage
643    }
644 
645    SendMessage(shellSocketFD, "ack");
646    LOG("ServiceManagementLayer:: Done setting active mission.\n");
647    //printf("\nhere ---%d, %d---\n", miss[activeMission].services[0].componentID, miss[activeMission].services[1].componentID);
648}
649
650/* CALLED BY: PerformActiveMission
651 * INPUTS: |sourceID| ID of the service that is being processed
652 * OUTPUTS: <none>
653 *
654 * DESCRIPTION: This is a helper method for the "PerformActiveMission" function
655 * NOTE: This function has changed durrastically from the previous implementation
656 * Takes an ID of a service
657 * For that service, finds inputs in DB and forwords those on to the engine after sending comm-starting messages
658 * Afterwords, listenes for the outputs so that it can store those in the database for future services or the overall output
659 */
660void
661ServiceManagementLayer::TransactData(int32_t sourceID)
662{
663   // LOG("ServiceManagementLayer:: Data transaction occuring.\n");
664    char buffer[256];
665    std::string data;
666    char* cols[] = {(char *)"Tag", (char *)"Data"};
667    int i = 0;
668    char *token;
669
670   //Send a message directly to the shell
671   if(miss[activeMission].services[sourceID].name.find("shell")!=string::npos)
672   {
673    int k = 0;
674    shellFound=true;
675    while(k<10 && !miss[activeMission].input[k].empty()){
676        k++;
677    }
678    sprintf(buffer, "%d", k);
679    SendMessage(shellSocketFD, buffer);
680    for(int t = 0; t < k; t++){
681        memset(buffer, 0 , 256);
682            _data_DB->command="select ";
683           _data_DB->command.append(_data_DB->tablename);
684            _data_DB->command.append(".* from ");
685            _data_DB->command.append(_data_DB->tablename);
686            _data_DB->command.append(" where Tag=='");
687        _data_DB->command.append(miss[activeMission].input[t]);
688        _data_DB->command.append("';");
689            sqlite3_stmt * pStatement;
690            int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), -1, &pStatement, NULL);
691            if (rc == SQLITE_OK){
692                if (sqlite3_step(pStatement) == SQLITE_ROW)
693                data=((const char*) sqlite3_column_text(pStatement, 1));
694                else {
695                printf("3data_DB:: Data not yet in DB., %s\n", _data_DB->command.c_str());
696            rc=31337;
697            }
698            }
699        else {
700            printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command.c_str());
701            }
702            sqlite3_finalize(pStatement);
703        token = strtok((char *)data.c_str(), "@");
704        token = strtok(NULL, "@");
705        SendMessage(shellSocketFD, token);
706        token = strtok(NULL, "@");
707        SendMessage(shellSocketFD, token);
708    }
709    return;
710   }
711
712    //If this is a service command and not a shell command...
713    //Transmission starting messages
714    SendMessage(miss[activeMission].services[sourceID].socketFD, "request_optimization_service");
715    SendMessage(miss[activeMission].services[sourceID].socketFD, miss[activeMission].services[sourceID].name.c_str());
716
717   //If the service takes a parameter, feed that parameter in
718   if(!miss[activeMission].services[sourceID].parameter.empty()){
719    //printf("sending parameter!\n");
720    SendMessage(miss[activeMission].services[sourceID].socketFD, "1");
721    SendMessage(miss[activeMission].services[sourceID].socketFD, "parameter");
722    SendMessage(miss[activeMission].services[sourceID].socketFD, miss[activeMission].services[sourceID].parameter.c_str());
723    }
724
725
726    //Load and transmit the input data
727    while(i < 10 && !miss[activeMission].services[sourceID].input[i].empty()){
728        _data_DB->command="select ";
729       _data_DB->command.append(_data_DB->tablename);
730        _data_DB->command.append(".* from ");
731        _data_DB->command.append(_data_DB->tablename);
732        _data_DB->command.append(" where Tag=='");
733    _data_DB->command.append(miss[activeMission].services[sourceID].input[i]);
734        _data_DB->command.append("';");
735        sqlite3_stmt * pStatement;
736        int rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), -1, &pStatement, NULL);
737        if (rc == SQLITE_OK){
738            if (sqlite3_step(pStatement) == SQLITE_ROW)
739             data.append((const char*) sqlite3_column_text(pStatement, 1));
740            else {
741                printf("2data_DB:: Data not yet in DB.\n");
742            rc=31337;
743        }
744        }
745    else {
746        printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command.c_str());
747        }
748        sqlite3_finalize(pStatement);
749
750        token = strtok((char *)data.c_str(), "@");
751    while(token){
752        SendMessage(miss[activeMission].services[sourceID].socketFD, token);
753        token = strtok(NULL, "@");
754    }
755    i++;
756    data.clear();
757    }
758    int32_t j = 0;
759   
760    //Receive and store the output data
761    while(j < 10 && !miss[activeMission].services[sourceID].output[j].empty()){
762    int rc;
763    memset(buffer, 0, 256);
764    //Read the number of datapairs for this output
765    ReadMessage(miss[activeMission].services[sourceID].socketFD, buffer);
766    data.append(buffer);
767    data.append("@");
768    int t = atoi(buffer);
769    for(int k = 0; k < t; k++){
770        //Read the datapairs incrementally and deliminate it with the "@" symbol
771        memset(buffer, 0, 256);
772        ReadMessage(miss[activeMission].services[sourceID].socketFD, buffer);
773        data.append(buffer);
774        data.append("@");
775        memset(buffer, 0, 256);
776        ReadMessage(miss[activeMission].services[sourceID].socketFD, buffer);
777        data.append(buffer);
778        data.append("@");
779    }
780
781    _data_DB->command="insert or replace into ";
782        _data_DB->command.append(_data_DB->tablename);
783          _data_DB->command.append(" (");
784        _data_DB->command.append(cols[0]);
785        _data_DB->command.append(", ");
786    _data_DB->command.append(cols[1]);
787    _data_DB->command.append(") ");
788    _data_DB->command.append(" values('");   
789    _data_DB->command.append(miss[activeMission].services[sourceID].output[j]);
790    _data_DB->command.append("', '");
791    _data_DB->command.append(data);
792    _data_DB->command.append("');");
793        char *errorMsg;
794       rc = sqlite3_exec(_data_DB->db, _data_DB->command.c_str(), callback, 0, &errorMsg);
795       if( rc!=SQLITE_OK && rc!=101 )
796           fprintf(stderr, "SQL error: %s\n", errorMsg);
797        //printf("S: done putting ouptut data into DB for ID#='%d', data=%s\n", sourceID, data.c_str());
798    j++;
799        data.clear();
800    }
801    //printf("done transact data!\n");
802   // LOG("ServiceManagementLayer:: Finished with data transaction.\n");
803
804
805    /*printf("\n\n\n");
806    // generate commandi
807    strcpy(_data_DB->command, "select ");
808    strcat(_data_DB->command, _data_DB->tablename);
809    strcat(_data_DB->command, ".* from ");
810    strcat(_data_DB->command, _data_DB->tablename);
811    strcat(_data_DB->command, ";");
812
813    // execute print (select all)  command   
814    char *errorMsg;
815    int rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
816    if( rc!=SQLITE_OK && rc!=101 )
817        fprintf(stderr, "SQL error: %s\n", errorMsg);
818    printf("database %s, table %s:\n", _data_DB->filename, _data_DB->tablename);
819    printf("\n\n\n");*/
820}
821
822
823
824/* CALLED BY: MessageHandler
825 * INPUTS: <none>
826 * OUTPUTS: <none>
827 *
828 * DESCRIPTION: This function works by first sending the inputs from the shell to the appropriate components
829 * The first service should begin immeadiately, as should any others who have all of their input parameters
830 * When they complete, the output path is found and the data is transfered as it becomes available
831 * Presumably at this point the second function has all of it's parameters, so it begins to compute, and the cycle repeats
832 * 
833 *
834 * Rules for active missions (currently)
835 * -Five inputs/outputs per service and per mission
836 * -All ordering constraints have been relaxed in this version; all data is stored locally and only sent when requested
837 * -If and while support fully implemented - up to three levels (if's can be nested, but dowhiles cannot)
838 * -For dowhiles, assumes loop condition determined on last line
839 * -IMPORTANT: DB uses '@' to seperate individual statements; using '@' in the data stream will result in incorrect behavior
840 */
841
842//WHILE
843void
844ServiceManagementLayer::PerformActiveMission()
845{
846    //printf("start PAM\n");
847    uint16_t i = 0, t;
848    shellFound = false;
849    std::string data_param, data_obsv, data;
850    std::string input;
851    std::string check;
852    char buffer[256];
853    char buffer1[256];
854    std::string token, token2;
855    std::string data2;
856    int rc;
857    char *errorMsg;
858    char* cols[] = {(char *)"Tag", (char *)"Data"};
859
860    LOG("ServiceManagementLayer:: Received PerformActiveMission command.\n");
861
862    //Get the inputs
863    memset(buffer, 0, 256);
864    //Needed to read the zero passed in by GOP as the number of observables
865    ReadMessage(shellSocketFD, buffer);
866
867
868    /* Receive Set of Parameters */
869    memset(buffer, 0, 256);
870    ReadMessage(shellSocketFD, buffer);
871    t=atoi(buffer);
872    for(int m = 0; m < t; m++) {
873        memset(buffer1, 0, 256);
874        ReadMessage(shellSocketFD, buffer1);
875    _data_DB->command="insert into ";
876        _data_DB->command.append(_data_DB->tablename);
877          _data_DB->command.append(" (");
878        _data_DB->command.append(cols[0]);
879        _data_DB->command.append(", ");
880    _data_DB->command.append(cols[1]);
881    _data_DB->command.append(") ");
882        memset(buffer, 0, 256);
883        ReadMessage(shellSocketFD, buffer);
884    _data_DB->command.append(" values('");
885    _data_DB->command.append(buffer1);
886    _data_DB->command.append("', '1@");
887    _data_DB->command.append(buffer1);
888    _data_DB->command.append("@");
889    _data_DB->command.append(buffer);
890    _data_DB->command.append("');");
891       rc = sqlite3_exec(_data_DB->db, _data_DB->command.c_str(), callback, 0, &errorMsg);
892       if( rc!=SQLITE_OK && rc!=101 )
893           fprintf(stderr, "SQL error: %s\n", errorMsg);
894    }
895
896    //Useful for spotchecking what's in the database
897    /*printf("\n\n\n");
898    // generate commandi
899    strcpy(_data_DB->command, "select ");
900    strcat(_data_DB->command, _data_DB->tablename);
901    strcat(_data_DB->command, ".* from ");
902    strcat(_data_DB->command, _data_DB->tablename);
903    strcat(_data_DB->command, ";");
904
905    // execute print (select all)  command 
906    rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
907    if( rc!=SQLITE_OK && rc!=101 )
908        fprintf(stderr, "SQL error: %s\n", errorMsg);
909    printf("database %s, table %s:\n", _data_DB->filename, _data_DB->tablename);
910    printf("\n\n\n");*/
911
912
913    i=0;
914    int32_t numstatements[3] = {0,0,0};
915    while(i < miss[activeMission].numServices)
916    {
917    if(miss[activeMission].services[i].name.compare("if")==0)
918    {
919       //printf("L0:if detected\n");
920        input.clear();
921        check.clear();
922        int t;
923        for(t = 0; t < 10; t++){
924        if(!miss[activeMission].services[i].output[t].empty()){
925            input=miss[activeMission].services[i-numstatements[0]-1].output[t];
926            _data_DB->command="SELECT ";
927            _data_DB->command.append(_data_DB->tablename);
928            _data_DB->command.append(".* from ");
929            _data_DB->command.append(_data_DB->tablename);
930            _data_DB->command.append(" where Tag=='");
931            _data_DB->command.append(input);
932            _data_DB->command.append("';");
933            sqlite3_stmt * pStatement;
934            rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), -1, &pStatement, NULL);
935            if (rc == SQLITE_OK){
936            if (sqlite3_step(pStatement) == SQLITE_ROW)
937                 data = (const char *) sqlite3_column_text(pStatement, 1);
938            else {
939                printf("1 data_DB:: Data not yet in DB.\n");
940                rc=31337;
941            }
942            } else {
943            printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command.c_str());
944            }
945                sqlite3_finalize(pStatement);
946            //printf("data=%s\n", data.c_str());
947            int pos = data.find_last_of("@", data.length()-2);
948            token = data.substr(pos+1);
949            token.erase(token.length()-1);
950            //printf("token=%s, %d\n", token.c_str(), pos);
951        data.clear();
952            break;
953        }
954        }
955        //printf("Level 0:--- %s  %s---\n", miss[activeMission].services[i].output[t].c_str(), token);
956        bool doit = false;
957        if(miss[activeMission].services[i].output[t].find(">") != string::npos){
958            std::string data2;
959            _data_DB->command="SELECT ";
960            _data_DB->command.append(_data_DB->tablename);
961            _data_DB->command.append(".* from ");
962            _data_DB->command.append(_data_DB->tablename);
963            _data_DB->command.append(" where Tag=='");
964            _data_DB->command.append(miss[activeMission].services[i].output[t].erase(0, 1));
965            _data_DB->command.append("';");
966            sqlite3_stmt * pStatement;
967            rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), -1, &pStatement, NULL);
968            if (rc == SQLITE_OK){
969            if (sqlite3_step(pStatement) == SQLITE_ROW)
970                 data2 = (const char *) sqlite3_column_text(pStatement, 1);
971            else {
972                printf("2 data_DB:: Data not yet in DB.\n");
973                rc=31337;
974            }
975            } else {
976            printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command.c_str());
977            }
978            sqlite3_finalize(pStatement);
979
980            int pos = data2.find_last_of("@", data2.length()-2);
981            token2 = data2.substr(pos+1);
982            token2.erase(token2.length()-1);
983            //printf("token2=%s, %d\n", token2.c_str(), pos);
984            if(atof(token.c_str()) > atof(token2.c_str()))
985            doit=true;
986            //printf("%s %s\n", buffer, token);
987        }
988        else if (miss[activeMission].services[i].output[t].find(token) != string::npos)
989                doit=true;
990        if(doit){
991        //printf("Level 0:if taken\n");
992        for(uint16_t k = i+1; k <= i+miss[activeMission].services[i].num_conds; k++){
993            if(miss[activeMission].services[k].name.compare("if")==0){
994            //printf("Level 1:if detected\n");
995                input.clear();
996                check.clear();
997                for(t = 0; t < 10; t++){
998                if(!miss[activeMission].services[k].output[t].empty()){
999                    input=miss[activeMission].services[k-numstatements[1]-1].output[t];
1000                        _data_DB->command="SELECT ";
1001                        _data_DB->command.append(_data_DB->tablename);
1002                       _data_DB->command.append(".* from ");
1003                       _data_DB->command.append(_data_DB->tablename);
1004                      _data_DB->command.append(" where Tag=='");
1005                     _data_DB->command.append(input);
1006                    _data_DB->command.append("';");
1007                    sqlite3_stmt * pStatement;
1008                    rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), -1, &pStatement, NULL);
1009                    if (rc == SQLITE_OK){
1010                    if (sqlite3_step(pStatement) == SQLITE_ROW)
1011                         data = (const char *) sqlite3_column_text(pStatement, 1);
1012                    else {
1013                        printf("3 data_DB:: Data not yet in DB.\n");
1014                        rc=31337;
1015                    }
1016                    } else {
1017                    printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command.c_str());
1018                    }
1019                        sqlite3_finalize(pStatement);
1020                    //printf("Level 1:data=%s\n", data.c_str());
1021                    int pos = data.find_last_of("@", data.length()-2);
1022                    token = data.substr(pos+1);
1023                    token.erase(token.length()-1);
1024                    //printf("Level 1:token=%s\n", token);
1025                    break;
1026                }
1027                }
1028                bool doit = false;
1029                if(miss[activeMission].services[k].output[t].find(">") != string::npos){
1030                    std::string data2;
1031                        _data_DB->command="SELECT ";
1032                    _data_DB->command.append(_data_DB->tablename);
1033                    _data_DB->command.append(".* from ");
1034                    _data_DB->command.append(_data_DB->tablename);
1035                    _data_DB->command.append(" where Tag=='");
1036                    _data_DB->command.append(miss[activeMission].services[k].output[t].erase(0, 1));
1037                    _data_DB->command.append("';");
1038                    sqlite3_stmt * pStatement;
1039                    rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), -1, &pStatement, NULL);
1040                    if (rc == SQLITE_OK){
1041                    if (sqlite3_step(pStatement) == SQLITE_ROW)
1042                         data2 = (const char *) sqlite3_column_text(pStatement, 1);
1043                    else {
1044                        printf("4 data_DB:: Data not yet in DB.\n");
1045                        rc=31337;
1046                    }
1047                    } else {
1048                    printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command.c_str());
1049                    }
1050                        sqlite3_finalize(pStatement);
1051                    int pos = data2.find_last_of("@", data2.length()-2);
1052                    token2 = data2.substr(pos+1);
1053                    token2.erase(token2.length()-1);
1054                        //printf("token=%s token2=%s\n", token.c_str(), token2.c_str());
1055                        if(atof(token.c_str()) > atof(token2.c_str()))
1056                        doit=true;
1057                }
1058                else if (miss[activeMission].services[k].output[t].find(token) != string::npos)
1059                doit=true;
1060                if(doit){
1061                //printf("Level 1:if taken\n");
1062                for(uint16_t j = k+1; j <= k+miss[activeMission].services[k].num_conds; j++){
1063                    if(miss[activeMission].services[j].name.compare("if")==0){
1064                    //printf("Level 2:if detected\n");
1065                        input.clear();
1066                        check.clear();
1067                        for(t = 0; t < 10; t++){
1068                        if(!miss[activeMission].services[j].output[t].empty()){
1069                            input=miss[activeMission].services[j-numstatements[2]-1].output[t];
1070                                   _data_DB->command="SELECT ";
1071                                _data_DB->command.append(_data_DB->tablename);
1072                               _data_DB->command.append(".* from ");
1073                               _data_DB->command.append(_data_DB->tablename);
1074                              _data_DB->command.append(" where Tag=='");
1075                             _data_DB->command.append(input);
1076                            _data_DB->command.append("';");
1077                            sqlite3_stmt * pStatement;
1078                            rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), -1, &pStatement, NULL);
1079                            if (rc == SQLITE_OK){
1080                            if (sqlite3_step(pStatement) == SQLITE_ROW)
1081                                 data = (const char *) sqlite3_column_text(pStatement, 1);
1082                            else {
1083                                printf("5 data_DB:: Data not yet in DB.\n");
1084                                rc=31337;
1085                            }
1086                            } else {
1087                            printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command.c_str());
1088                            }
1089                                sqlite3_finalize(pStatement);
1090                            //printf("data=%s\n", data.c_str());
1091                            int pos = data.find_last_of("@", data.length()-2);
1092                            token = data.substr(pos+1);
1093                            token.erase(token.length()-1);
1094                            //printf("token=%s\n", token.c_str());
1095                            data.clear();
1096                            break;
1097                        }
1098                        }
1099                        bool doit = false;
1100                        if(miss[activeMission].services[j].output[t].find(">") != string::npos){
1101                            _data_DB->command="SELECT ";
1102                            _data_DB->command.append(_data_DB->tablename);
1103                            _data_DB->command.append(".* from ");
1104                           _data_DB->command.append(_data_DB->tablename);
1105                            _data_DB->command.append(" where Tag=='");
1106                            _data_DB->command.append(miss[activeMission].services[j].output[t].erase(0, 1));
1107                            _data_DB->command.append("';");
1108                            sqlite3_stmt * pStatement;
1109                            rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), -1, &pStatement, NULL);
1110                            if (rc == SQLITE_OK){
1111                            if (sqlite3_step(pStatement) == SQLITE_ROW)
1112                                 data2 = (const char *) sqlite3_column_text(pStatement, 1);
1113                            else {
1114                                printf("6 data_DB:: Data not yet in DB.\n");
1115                                rc=31337;
1116                            }
1117                            } else {
1118                            printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command.c_str());
1119                            }
1120                                sqlite3_finalize(pStatement);
1121
1122                        int pos = data2.find_last_of("@", data2.length()-2);
1123                        token2 = data2.substr(pos+1);
1124                        token2.erase(token2.length()-1);
1125                            if(atof(token.c_str()) > atof(token2.c_str()))
1126                            doit=true;
1127                        data.clear();
1128                        }
1129                        else if (miss[activeMission].services[j].output[t].find(token) != string::npos)
1130                        doit=true;
1131                        if(doit){
1132                        //printf("Level 1:if taken\n");
1133                        for(uint16_t l = j+1; l <= j+miss[activeMission].services[j].num_conds; l++){
1134                            TransactData(l);
1135                        }
1136                        }
1137                        else
1138                        //printf("Level 2:if not taken\n");
1139                        numstatements[2] +=miss[activeMission].services[j].num_conds+1;
1140                        j+=miss[activeMission].services[j].num_conds;
1141                        //printf("Level 2:doneif %d, %d, %d\n", numstatements, miss[activeMission].services[i].num_conds, i);
1142                    }else if(miss[activeMission].services[j].name.compare("dowhile")==0){
1143                        numstatements[0]=0;
1144                        //printf("Level 2:while detected\n");
1145                        while(true){
1146                            uint16_t l;
1147                            for(l = j+1; l <= j+miss[activeMission].services[j].num_conds; l++){
1148                            TransactData(l);
1149                            }
1150                            data.clear();
1151                            input.clear();
1152                            check.clear();
1153                            int t;
1154                            for(t = 0; t < 10; t++){
1155                            if(!miss[activeMission].services[j].output[t].empty()){
1156                                input=miss[activeMission].services[l-2].output[t];
1157                                //printf("%s\n",input.c_str());
1158                                _data_DB->command="SELECT ";
1159                                _data_DB->command.append(_data_DB->tablename);
1160                                _data_DB->command.append(".* from ");
1161                                _data_DB->command.append(_data_DB->tablename);
1162                                _data_DB->command.append(" where Tag=='");
1163                                _data_DB->command.append(input);
1164                                _data_DB->command.append("';");
1165                                sqlite3_stmt * pStatement;
1166
1167                                rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), -1, &pStatement, NULL);
1168                                if (rc == SQLITE_OK){
1169                                if (sqlite3_step(pStatement) == SQLITE_ROW)
1170                                     data = (const char *) sqlite3_column_text(pStatement, 1);
1171                                else {
1172                                    printf("7 data_DB:: Data not yet in DB.: %s\n", _data_DB->command.c_str());
1173                                    rc=31337;
1174                                }
1175                                } else {
1176                                  printf("data_DB:: SQL statement error. rc = %i\n%s\n",rc,_data_DB->command.c_str());
1177                                }
1178                                    sqlite3_finalize(pStatement);
1179                                //printf("Level 2:data=%s\n", data.c_str());
1180                                    int pos = data.find_last_of("@", data.length()-2);
1181                                    token = data.substr(pos+1);
1182                                    token.erase(token.length()-1);
1183                                //printf("Level 2:token=%s\n", token);
1184                                break;
1185                            }
1186                            }
1187                            //printf("Level 2:--- %s  %s---\n", miss[activeMission].services[j].output[t].c_str(), token);
1188                            if(miss[activeMission].services[j].output[t].find(token) != string::npos){
1189                            //printf("Level 2:while taken again!\n");
1190                            }
1191                            else {
1192                            //printf("Level 2:no more while\n");
1193                            break;}
1194                        }
1195                        j+=miss[activeMission].services[j].num_conds;
1196                    }
1197                    else{
1198                        //printf("Level 2: no conditional\n");
1199                        numstatements[2]=0;
1200                            TransactData(j);
1201                    }
1202                }
1203                }
1204                else{
1205                //printf("Level 1: if not taken\n");
1206                }
1207                    numstatements[1] +=miss[activeMission].services[k].num_conds+1;
1208                    k+=miss[activeMission].services[k].num_conds;
1209                //printf("doneif %d, %d, %d\n", numstatements, miss[activeMission].services[i].num_conds, i);
1210            }else if(miss[activeMission].services[k].name.compare("dowhile")==0){
1211                numstatements[0]=0;
1212                //printf("Level 1: while detected\n");
1213                while(true){
1214                uint16_t j;
1215                    for(j = k+1; j <= k+miss[activeMission].services[k].num_conds; j++){
1216                    TransactData(j);
1217                    }
1218                    data.clear();
1219                    input.clear();
1220                    check.clear();
1221                    int t;
1222                    for(t = 0; t < 10; t++){
1223                    if(!miss[activeMission].services[k].output[t].empty()){
1224                        input=miss[activeMission].services[j-1].output[t];
1225                        _data_DB->command="SELECT ";
1226                        _data_DB->command.append(_data_DB->tablename);
1227                        _data_DB->command.append(".* from ");
1228                        _data_DB->command.append(_data_DB->tablename);
1229                        _data_DB->command.append(" where Tag=='");
1230                        _data_DB->command.append(input);
1231                        _data_DB->command.append("';");
1232                        sqlite3_stmt * pStatement;
1233                        rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), -1, &pStatement, NULL);
1234                        if (rc == SQLITE_OK){
1235                        if (sqlite3_step(pStatement) == SQLITE_ROW)
1236                             data = (const char *) sqlite3_column_text(pStatement, 1);
1237                        else {
1238                            printf("8 data_DB:: Data not yet in DB.\n");
1239                            rc=31337;
1240                        }
1241                        } else {
1242                        printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command.c_str());
1243                        }
1244                            sqlite3_finalize(pStatement);
1245                        //printf("Level 1:data=%s\n", data.c_str());
1246                        int pos = data.find_last_of("@", data.length()-2);
1247                        token = data.substr(pos+1);
1248                        token.erase(token.length()-1);
1249                        //printf("Level 1:token=%s\n", token);
1250                        break;
1251                    }
1252                    }
1253                    //printf("Level 1:--- %s  %s---\n", miss[activeMission].services[k].output[t].c_str(), token);
1254                    if(miss[activeMission].services[k].output[t].find(token) != string::npos){
1255                    //printf("Level 1:while taken again!\n");
1256                    }
1257                    else {
1258                    //printf("Level 1:While finished\n");
1259                    break;}
1260                }
1261                k+=miss[activeMission].services[k].num_conds;
1262            }
1263            else{
1264                //printf("Level1:No conditional\n");
1265                numstatements[1]=0;
1266                    TransactData(k);
1267            }
1268        }
1269        }
1270            numstatements[0] +=miss[activeMission].services[i].num_conds+1;
1271        i+=miss[activeMission].services[i].num_conds;
1272    }
1273    else if(miss[activeMission].services[i].name.compare("dowhile")==0)
1274    {
1275        numstatements[0]=0;
1276        //printf("Level 0: while detected\n");
1277        while(true){
1278        uint16_t k;
1279            for(k = i+1; k <= i+miss[activeMission].services[i].num_conds; k++){
1280            TransactData(k);
1281            }
1282            data.clear();
1283            input.clear();
1284            check.clear();
1285            int t;
1286            for(t = 0; t < 10; t++){
1287            if(!miss[activeMission].services[i].output[t].empty()){
1288                input=miss[activeMission].services[k-1].output[t];
1289                _data_DB->command="SELECT ";
1290                _data_DB->command.append(_data_DB->tablename);
1291                _data_DB->command.append(".* from ");
1292                _data_DB->command.append(_data_DB->tablename);
1293                _data_DB->command.append(" where Tag=='");
1294                _data_DB->command.append(input);
1295                _data_DB->command.append("';");
1296                sqlite3_stmt * pStatement;
1297                rc = sqlite3_prepare_v2(_data_DB->db, _data_DB->command.c_str(), -1, &pStatement, NULL);
1298                if (rc == SQLITE_OK){
1299                if (sqlite3_step(pStatement) == SQLITE_ROW)
1300                     data = (const char *) sqlite3_column_text(pStatement, 1);
1301                else {
1302                    printf("10data_DB:: Data not yet in DB.\n");
1303                    rc=31337;
1304                }
1305                } else {
1306                printf("data_DB:: Error executing SQL statement. rc = %i\n%s\n",rc,_data_DB->command.c_str());
1307                }
1308                    sqlite3_finalize(pStatement);
1309                int pos = data.find_last_of("@", data.length()-2);
1310                token = data.substr(pos+1);
1311                token.erase(token.length()-1);
1312                break;
1313            }
1314            }
1315            //printf("Level 0:--- %s  %s---\n", miss[activeMission].services[i].output[t].c_str(), token);
1316            if(miss[activeMission].services[i].output[t].find(token) != string::npos){
1317            //printf("Level 0:while taken again!\n");
1318            }
1319            else {
1320            //printf("Level 0:no more while\n");
1321            break;}
1322        }
1323        i+=miss[activeMission].services[i].num_conds;
1324    }
1325    else{
1326        numstatements[0]=0;
1327        //printf("Level 0: No conditional\n");
1328        TransactData(i);}
1329    i++;
1330    }
1331    i=0;
1332    data.clear();
1333
1334    if(!shellFound)
1335    {
1336    int k = 0;
1337    while(k<10 && !miss[activeMission].input[k].empty()){
1338        k++;
1339    }
1340    sprintf(buffer, "%d", k);
1341    SendMessage(shellSocketFD, buffer);
1342    for(int t = 0; t < k; t++){
1343        SendMessage(shellSocketFD, miss[activeMission].input[t].c_str());
1344        SendMessage(shellSocketFD, "0");
1345    }
1346    }
1347
1348
1349    LOG("ServiceManagementLayer:: Done performing active mission.\n");
1350    /*
1351    strcpy(_data_DB->command, "select ");
1352    strcat(_data_DB->command, _data_DB->tablename);
1353    strcat(_data_DB->command, ".* from ");
1354    strcat(_data_DB->command, _data_DB->tablename);
1355    strcat(_data_DB->command, ";");
1356
1357    // execute print (select all)  command 
1358    rc = sqlite3_exec(_data_DB->db, _data_DB->command, callback, 0, &errorMsg);
1359    if( rc!=SQLITE_OK && rc!=101 )
1360        fprintf(stderr, "SQL error: %s\n", errorMsg);
1361    printf("database %s, table %s:\n", _data_DB->filename, _data_DB->tablename);
1362    printf("\n\n\n");*/
1363}
1364
1365
1366/* CALLED BY: MessageHandler
1367 * INPUTS: <none>
1368 * OUTPUTS: <none>
1369 *
1370 * DESCRIPTION: Print a list of the services currently registered and the ID's of the components that registered them
1371 */
1372void
1373ServiceManagementLayer::ListServices()
1374{
1375    _services_DB->command="select ";
1376    _services_DB->command.append(_services_DB->tablename);
1377    _services_DB->command.append(".* from ");
1378    _services_DB->command.append(_services_DB->tablename);
1379    _services_DB->command.append(";");
1380
1381    // execute print (select all)  command   
1382    char *errorMsg;
1383    int rc = sqlite3_exec(_services_DB->db, _services_DB->command.c_str(), callback, 0, &errorMsg);
1384    if( rc!=SQLITE_OK && rc!=101 )
1385        fprintf(stderr, "SQL error: %s\n", errorMsg);
1386    printf("database %s, table %s:\n", _services_DB->filename.c_str(), _services_DB->tablename.c_str());
1387}
1388
1389/* CALLED BY: Reset
1390 * INPUTS: <none>
1391 * OUTPUTS: <none>
1392 *
1393 * DESCRIPTION: Clear and reinitialize the mission array, then reload the configuration file
1394 */
1395void
1396ServiceManagementLayer::ReloadConfiguration()
1397{
1398    LOG("ServiceManagementLayer:: Reloading Configuration.\n");
1399    free(miss);
1400    miss = new Mission[10];
1401    for(int i = 0; i < 10; i++)
1402        miss[i].services = new Service[30];
1403    LoadConfiguration(_SML_Config.c_str(), miss);
1404}
1405
1406/* CALLED BY: constructor
1407 * INPUTS: |SML_Config| Address (either relitive or full) of the XML file containing mission data
1408 *        |mList| Mission array to be modified
1409 * OUTPUTS: <none>
1410 *
1411 * DESCRIPTION: IMPORTANT - See formatting instructions for correct parsing of data
1412 * Can currently handle 10 inputs and 10 outputs per service, but easily expandable
1413 * Also, can handle two layer of nested conditional statements, but could
1414 * be expanded to meet additional needs.
1415 *
1416 * Components assigned to mission during "set active mission" stage so that
1417 * components can still continue to register after the configuration is loaded
1418 */
1419void
1420ServiceManagementLayer::LoadConfiguration(const char *SML_Config, Mission* &mList)
1421{
1422    TiXmlElement *pMission;
1423    TiXmlElement *pService;
1424    TiXmlElement *pChild0, *pChild1, *pChild2, *pChild3, *pChild4;
1425    TiXmlHandle hRoot(0);
1426    printf("ServiceManagementLayer:: Loading Configuration.\n");
1427    TiXmlDocument doc(".");
1428    doc.LoadFile(SML_Config);
1429    bool loadOkay = doc.LoadFile();
1430    if(!loadOkay)
1431        printf("Loading SML configuration failed: %s\n", SML_Config);
1432
1433    TiXmlHandle hDoc(&doc);
1434   
1435    pMission = hDoc.FirstChildElement().Element();
1436
1437    if(!pMission)
1438        printf("No valid root!");
1439
1440    hRoot = TiXmlHandle(pMission);
1441    pService = pMission->FirstChildElement();
1442    int32_t mission_num = 0;
1443    //Iterate through the missions
1444    for(pChild0 = pMission->FirstChildElement(); pChild0 ; \
1445        pChild0 = pChild0->NextSiblingElement())
1446    {
1447    int32_t service_num = 0;
1448    uint16_t cond_array[] = {0, 0, 0};
1449   
1450        for(pChild1  = (pChild0->FirstChildElement())->FirstChildElement(); pChild1; \
1451              pChild1  = pChild1->NextSiblingElement())
1452        {
1453        int32_t conditional_0 = service_num;
1454        for(pChild2 = pChild1->FirstChildElement(); \
1455        pChild2; pChild2 = pChild2->NextSiblingElement())
1456        {
1457        service_num++;
1458        int32_t conditional_1 = service_num;
1459        for(pChild3 = pChild2->FirstChildElement(); \
1460            pChild3; pChild3 = pChild3->NextSiblingElement())
1461        {
1462            service_num++;
1463            int32_t conditional_2 = service_num;
1464            for(pChild4 = pChild3->FirstChildElement(); \
1465                pChild4; pChild4 = pChild4->NextSiblingElement())
1466            {
1467                   service_num++;
1468                if(pChild4->Attribute("name"))
1469                    mList[mission_num].services[service_num].name = pChild4->Attribute("name");
1470                else
1471                    mList[mission_num].services[service_num].name = pChild4->Value();
1472                for(int i = 1; i <= 10; i++) {
1473                    char buffer[9]="input";
1474                    sprintf(buffer, "%s%d", buffer, i);
1475                    //printf("buffer=%s\n", buffer);
1476                    if(pChild4->Attribute(buffer))
1477                        mList[mission_num].services[service_num].input[i-1] = pChild4->Attribute(buffer);
1478                    char buffer2[9]="output";
1479                    sprintf(buffer2, "%s%d", buffer2, i);
1480                    if(pChild4->Attribute(buffer2))
1481                    mList[mission_num].services[service_num].output[i-1] = pChild4->Attribute(buffer2);
1482                }
1483                if(pChild4->Attribute("parameter"))
1484                mList[mission_num].services[service_num].parameter = pChild4->Attribute("parameter");
1485                cond_array[2]++;
1486            }
1487            if(!strcmp(pChild3->Value(), "shell") || conditional_2 != service_num) {
1488                mList[mission_num].services[conditional_2].name = pChild3->Value();
1489            }
1490            else{
1491                mList[mission_num].services[service_num].name = pChild3->Attribute("name");
1492            }
1493            for(int i = 1; i <= 10; i++) {
1494                char buffer[9]="input";
1495                sprintf(buffer, "%s%d", buffer, i);
1496                if(pChild3->Attribute(buffer))
1497                mList[mission_num].services[conditional_2].input[i-1] = pChild3->Attribute(buffer);
1498                char buffer2[9]="output";
1499                sprintf(buffer2, "%s%d", buffer2, i);
1500                if(pChild3->Attribute(buffer2))
1501                mList[mission_num].services[conditional_2].output[i-1] = pChild3->Attribute(buffer2);
1502            }
1503                if(pChild3->Attribute("parameter"))
1504                mList[mission_num].services[conditional_2].parameter = pChild3->Attribute("parameter");
1505            mList[mission_num].services[conditional_2].num_conds = cond_array[2];
1506            cond_array[1]+=cond_array[2]+1;
1507            cond_array[2] = 0;
1508
1509
1510        }
1511        if(!strcmp(pChild2->Value(), "shell") || conditional_1 != service_num) {
1512            mList[mission_num].services[conditional_1].name = pChild2->Value();
1513        }
1514        else{
1515            mList[mission_num].services[service_num].name = pChild2->Attribute("name");
1516        }
1517           for(int i = 1; i <= 10; i++) {
1518            char buffer[9]="input";
1519            sprintf(buffer, "%s%d", buffer, i);
1520            if(pChild2->Attribute(buffer))
1521                mList[mission_num].services[conditional_1].input[i-1] = pChild2->Attribute(buffer);
1522            char buffer2[9]="output";
1523            sprintf(buffer2, "%s%d", buffer2, i);
1524            if(pChild2->Attribute(buffer2))
1525            mList[mission_num].services[conditional_1].output[i-1] = pChild2->Attribute(buffer2);
1526        }
1527            if(pChild2->Attribute("parameter"))
1528            mList[mission_num].services[conditional_1].parameter = pChild2->Attribute("parameter");
1529
1530        mList[mission_num].services[conditional_1].num_conds = cond_array[1];
1531        cond_array[0]+=cond_array[1]+1;
1532        cond_array[1] = 0;
1533        }
1534       
1535        if(!strcmp(pChild1->Value(), "shell") || conditional_0 != service_num) {
1536            mList[mission_num].services[conditional_0].name = pChild1->Value();
1537        }
1538        else{
1539        mList[mission_num].services[conditional_0].name = pChild1->Attribute("name");
1540        }
1541        for(int i = 1; i <= 10; i++) {
1542            char buffer[9]="input";
1543            sprintf(buffer, "%s%d", buffer, i);
1544            if(pChild1->Attribute(buffer))
1545                mList[mission_num].services[conditional_0].input[i-1] = pChild1->Attribute(buffer);
1546            char buffer2[9]="output";
1547            sprintf(buffer2, "%s%d", buffer2, i);
1548            if(pChild1->Attribute(buffer2))
1549            mList[mission_num].services[conditional_0].output[i-1] = pChild1->Attribute(buffer2);
1550        }
1551        if(pChild1->Attribute("parameter"))
1552            mList[mission_num].services[conditional_0].parameter = pChild1->Attribute("parameter");
1553        mList[mission_num].services[conditional_0].num_conds = cond_array[0];
1554            cond_array[0] = 0;
1555        service_num++;
1556    }
1557   
1558    mList[mission_num].numServices = service_num;
1559    mList[mission_num].name = pChild0->Attribute("name");
1560        mList[mission_num].missionID = atoi(pChild0->Attribute("id"));
1561    for(int i = 1; i <= 10; i++) {
1562        char buffer[9]="param";
1563        sprintf(buffer, "%s%d", buffer, i);
1564        if(pChild0->Attribute(buffer)){
1565            mList[mission_num].input[i-1] = pChild0->Attribute(buffer);
1566        }
1567    }
1568    mission_num++;
1569    }
1570    LOG("ServiceManagementLayer:: Done Loading Configuration\n");
1571}
1572
1573/* CALLED BY: MessageHandler
1574 * INPUTS: |ID| The ID number of the engine to be registered
1575 * OUTPUTS: <none>
1576 *
1577 * DESCRIPTION: Sends a registration message onto the shell and sends the ACK back to the component
1578 */
1579void
1580ServiceManagementLayer::RegisterCognitiveEngine(int32_t ID)
1581{
1582    SendMessage(shellSocketFD, "register_engine_cognitive");
1583
1584    LOG("ServiceManagementLayer:: CE registration message forwarded to shell.\n");
1585    char buffer[256];
1586    memset(buffer, 0, 256);
1587    ReadMessage(shellSocketFD, buffer);
1588    SendMessage(CE_List[ID].FD, buffer);
1589
1590    TransferRadioConfiguration(ID);
1591    memset(buffer, 0, 256);
1592    TransferExperience(ID);
1593    memset(buffer, 0, 256);
1594    numberOfCognitiveEngines++;
1595    CE_Present = true;
1596}
1597
1598/* CALLED BY: MessageHandler
1599 * INPUTS: |ID| The ID number of the engine to have it's services deregistered
1600 * OUTPUTS: <none>
1601 *
1602 * DESCRIPTION: Deletes individual services from the DB
1603 * NOTE THAT this function only needs to be called if service deregistration is going
1604 * to be done at a different time than component deregistration; it is handled
1605 * more efficiently and directly during that deregistration process.
1606 */
1607void
1608ServiceManagementLayer::DeregisterServices(int32_t ID)
1609{
1610    char buffer[256];
1611    memset(buffer, 0, 256);
1612    ReadMessage(CE_List[ID].FD, buffer);
1613    _services_DB->command="DELETE FROM ";
1614    _services_DB->command.append(_services_DB->tablename);
1615    _services_DB->command.append(" WHERE ID_Num IN (SELECT ");
1616    char tmp[3];
1617    memset(tmp,0,3);
1618    sprintf(tmp, "%d", ID);
1619    _services_DB->command.append(tmp);
1620    _services_DB->command.append(" FROM ");
1621    _services_DB->command.append(_services_DB->tablename);
1622    _services_DB->command.append(" WHERE Service_Name");
1623    _services_DB->command.append("=='");
1624    _services_DB->command.append(buffer);
1625    _services_DB->command.append("');");
1626    char *errorMsg;
1627    int rc = sqlite3_exec(_services_DB->db, _services_DB->command.c_str(), callback, 0, &errorMsg);
1628    if( rc!=SQLITE_OK && rc!=101 )
1629        fprintf(stderr, "SQL error: %s\n", errorMsg);
1630}
1631
1632/* CALLED BY: MessageHandler
1633 * INPUTS: |ID| The ID number of the engine to have it's services deregistered
1634 * OUTPUTS: <none>
1635 *
1636 * DESCRIPTION: Deletes the contact info for the cognitive engine, forwards a deregistration message to the shell
1637 * Also, deletes the services from the DB
1638 */
1639void
1640ServiceManagementLayer::DeregisterCognitiveEngine(int32_t ID)
1641{
1642    LOG("ServiceManagementLayer:: CE deregistration message forwarded to shell.\n");
1643
1644    numberOfCognitiveEngines--;
1645    if(numberOfCognitiveEngines == 0)
1646        CE_Present = false;
1647
1648    SendMessage(shellSocketFD, "deregister_engine_cognitive");
1649    char buffer[256];
1650    memset(buffer, 0, 256);
1651    ReadMessage(shellSocketFD, buffer);
1652    SendMessage(CE_List[ID].FD, buffer);
1653    if(strcmp("deregister_ack", buffer) != 0) {
1654    ERROR(1, "SML:: Failed to close CE socket\n");
1655    }
1656
1657    //Deregister the services
1658    _services_DB->command="DELETE FROM ";
1659    _services_DB->command.append(_services_DB->tablename);
1660    _services_DB->command.append(" WHERE ");
1661    _services_DB->command.append("ID_Num");
1662    _services_DB->command.append("==");
1663    char tmp[3];
1664    memset(tmp,0,3);
1665    sprintf(tmp, "%d", ID);
1666    _services_DB->command.append(tmp);
1667    _services_DB->command.append(";");
1668    char *errorMsg;
1669    int rc = sqlite3_exec(_services_DB->db, _services_DB->command.c_str(), callback, 0, &errorMsg);
1670    if( rc!=SQLITE_OK && rc!=101 )
1671        fprintf(stderr, "SQL error: %s\n", errorMsg);
1672
1673
1674    CE_List[ID].FD = -1;
1675    CE_List[ID].ID_num = -1;
1676
1677    LOG("Cognitive Radio Shell:: CE Socket closed for engine #%d.\n", ID);
1678}
1679
1680
1681/* CALLED BY: test class
1682 * INPUTS: <none>
1683 * OUTPUTS: <none>
1684 *
1685 * DESCRIPTION: Sets up a server socket and listens for communication on either that or the shell socket
1686 */
1687void
1688ServiceManagementLayer::StartSMLServer()
1689{
1690    //printf("Ready for CE Signal! (registration done)\n");
1691    struct timeval selTimeout;
1692    int32_t running = 1;
1693    int32_t port, rc, new_sd = 1;
1694    int32_t desc_ready = 1;
1695        //If there is, call the MessageHandler with the Shell_Msg code of -1
1696    fd_set sockSet, shellSet;
1697
1698    cogEngSrv = CreateTCPServerSocket(SMLport);
1699    int32_t maxDescriptor = cogEngSrv;
1700
1701    if(InitializeTCPServerPort(cogEngSrv) == -1)
1702        ERROR(1,"Error initializing primary port\n");
1703
1704   
1705    while (running) {
1706        /* Zero socket descriptor vector and set for server sockets */
1707        /* This must be reset every time select() is called */
1708        FD_ZERO(&sockSet);
1709        FD_SET(cogEngSrv, &sockSet);
1710       
1711        for(uint16_t k = 0; k < Current_ID; k++){
1712        if(CE_List[k].ID_num != -1)
1713            FD_SET(CE_List[k].FD, &sockSet);
1714    }
1715        //printf("k=%d, CID=%d\n", k, CE_List[k].FD);
1716
1717        /* Timeout specification */
1718        /* This must be reset every time select() is called */
1719        selTimeout.tv_sec = 0;       /* timeout (secs.) */
1720        selTimeout.tv_usec = 0;            /* 0 microseconds */
1721    //Changed both to zero so that select will check messages from the shell instead of blocking
1722    //when there is no command from the CE's to be processed
1723
1724        //Check if there is a message on the socket waiting to be read
1725    rc = select(maxDescriptor + 1, &sockSet, NULL, NULL, &selTimeout);
1726        //printf("rc=%d\n", rc);
1727        if(rc == 0){
1728            //LOG("No echo requests for %i secs...Server still alive\n", 10);
1729   
1730            FD_ZERO(&shellSet);
1731            FD_SET(shellSocketFD, &shellSet);
1732            selTimeout.tv_sec = 0;
1733            selTimeout.tv_usec = 0;
1734            //Check if there is a message on the shell socket ready to be processed
1735            select(shellSocketFD + 1, &shellSet, NULL, NULL, &selTimeout);
1736            //printf("rc2=%d\n", rc2);
1737        //If there is, call the MessageHandler with the Shell_Msg code of -1
1738        if(FD_ISSET(shellSocketFD, &shellSet)){
1739        //printf("shell_msg, %d\n", rc2);
1740            MessageHandler(-1);}
1741    }
1742        else {
1743            desc_ready = rc;
1744            for(port = 0; port <= maxDescriptor && desc_ready > 0; port++) {
1745                if(FD_ISSET(port, &sockSet)) {
1746                    desc_ready -= 1;
1747
1748                    //Check if request is new or on an existing open descriptor
1749                    if(port == cogEngSrv) {
1750            //If new, assign it a descriptor and give it an ID
1751                        new_sd = AcceptTCPConnection(port);
1752             
1753                        if(new_sd < 0)
1754                            break;
1755
1756                        CE_List[Current_ID].FD = new_sd;
1757            CE_List[Current_ID].ID_num = Current_ID;
1758                        MessageHandler(Current_ID);
1759            Current_ID++;
1760   
1761            FD_SET(new_sd,&sockSet);
1762                        if(new_sd > maxDescriptor)
1763                           maxDescriptor = new_sd;
1764                    }
1765                    else {
1766            //If old, figure out which ID it coresponds to and handle it accordingly
1767            for(uint16_t z = 0; z < Current_ID; z++)
1768            {
1769                if(CE_List[z].FD == port){
1770                    MessageHandler(z);}
1771            }
1772                    }
1773                }
1774            }
1775    }
1776    }       
1777
1778    /* Close sockets */
1779    close(cogEngSrv);
1780
1781    //delete &cogEngSrv;
1782    return;
1783}
Note: See TracBrowser for help on using the browser.