root/vtcross/trunk/src/shell/cr_shell.cpp @ 178

Revision 178, 19.1 KB (checked in by bhilburn, 15 years ago)

More cleanup in the shell file. Starting to burn out on refactoring. Finaly
refactor commit for the day. Still tons to do in this file.

Line 
1/* Virginia Tech Cognitive Radio Open Source Systems
2 * Virginia Tech, 2009
3 *
4 * TODO LICENSE INFORMATION GOES HERE
5 */
6
7/* TODO DESCRIPTION OF FILE.
8 */
9
10
11#include <arpa/inet.h>
12#include <iostream>
13#include <netinet/in.h>
14#include <netdb.h>
15#include <fcntl.h>
16#include <sys/ioctl.h>
17#include <sys/mman.h>
18#include <sys/socket.h>
19#include <sys/types.h>
20#include <sys/wait.h>
21
22#include "tinyxml/tinyxml.h"
23#include "tinyxml/tinystr.h"
24
25#include "vtcross/common.h"
26#include "vtcross/components.h"
27#include "vtcross/containers.h"
28#include "vtcross/debug.h"
29#include "vtcross/error.h"
30#include "vtcross/socketcomm.h"
31
32
33using namespace std;
34
35
36#define CE_SERVER_PORT 30001
37#define PE_SERVER_PORT 30003
38
39
40void
41print_current_config(Utility* uList[], Parameter* pList[], \
42        Observable* oList[], CE_Info* ce_info)
43{
44        for(size_t i = 0; i < ce_info->numUtilities ; i++) {
45        LOG("Shell:: Utility: %s\n\tUnits: %s\n\tGoal: %s\n\tTarget: %f\n", \
46                uList[i]->name.c_str(), uList[i]->units.c_str(), \
47                uList[i]->goal.c_str(), uList[i]->target);
48        }
49
50        for(size_t i = 0; i < ce_info->numParameters; i++) {
51            LOG("Shell:: Radio Operation Profile has been sucessfully sent.\n");
52        LOG("Shell:: Parameter: %s\n\tUnits: %s\n\tMin: %f\n\t", \
53                pList[i]->name.c_str(), pList[i]->units.c_str(), \
54                pList[i]->min);
55        LOG("\tMax: %f\n\tStep: %f\n", pList[i]->max, pList[i]->step);
56
57                for(size_t j = 0; j < pList[i]->numAffects; j++) {
58                        LOG("\t\tAffect %s -> %s\n", pList[i]->affection_list[j].u->name.c_str(), \
59                    pList[i]->affection_list[j].relation.c_str());
60                }
61        }
62       
63    for(size_t i = 0; i < ce_info->numObservables; i++) {
64                LOG("Observable: %s\n", oList[i]->name.c_str());
65
66                for(size_t j = 0; j < oList[i]->numAffects; j++) {
67                        LOG("\t\tAffect %s -> %s ", oList[i]->affection_list[j].u->name.c_str(), \
68                    oList[i]->affection_list[j].relation.c_str());
69                }
70        }
71}
72
73
74// TODO should this function really be called parse 'ce' config?  Seems like it
75// affects the entire radio?
76// TODO Why are we always returning 1? Is this just a success variable? It's not
77// even being used when we call it...
78// TODO this function needs some serious comments
79int32_t
80parse_ce_config(TiXmlDocument* doc, Utility* u[], Parameter* p[], \
81        Observable* o[], CE_Info* ce_info)
82{
83
84        TiXmlElement *pElem;
85        TiXmlElement *pChild;
86        TiXmlElement *pChild1;
87        TiXmlElement *pSecondChild;
88        TiXmlHandle hDoc(doc);
89        TiXmlHandle hRoot(0);
90
91        int32_t count = 0;
92        size_t item_count = 0;
93    size_t affect_count = 0;
94        int32_t attribute_count = 0;
95    bool match_found = false;
96
97        pElem = hDoc.FirstChildElement().Element();
98
99        if(!pElem)
100        ERROR(1, "No valid root!");
101
102        hRoot = TiXmlHandle(pElem);
103
104        pElem = hRoot.FirstChild("utilities").Element();
105        pChild1 = hRoot.Child("utilities", count).Element();
106
107        for(pChild = pChild1->FirstChildElement("utility"); pChild; \
108            pChild = pChild->NextSiblingElement()) {
109
110                u[item_count] = new Utility;
111
112                const char *uName = pChild->Attribute("name");
113                if(uName)
114            u[item_count]->name = uName;       
115
116                const char *uUnits = pChild->Attribute("units");
117                if(uUnits)
118            u[item_count]->units = uUnits;
119
120                const char *uGoal = pChild->Attribute("goal");
121                if(uGoal)
122            u[item_count]->goal = uGoal;
123
124                if(pChild->QueryFloatAttribute("target", &u[item_count]->target) != TIXML_SUCCESS)
125            u[item_count]->target = -1;
126
127                item_count++;
128        }
129
130        ce_info->numUtilities = item_count;     
131        LOG("Initialize:: Parsed %d utilities.\n", ce_info->numUtilities);
132
133        item_count = 0;
134        pElem = hRoot.FirstChild("observables").Element();
135        pChild1 = hRoot.Child("observables", count).Element();
136
137        for(pChild = pChild1->FirstChildElement("observable"); pChild; \
138            pChild = pChild->NextSiblingElement()) {
139
140                const char *oName = pChild->Attribute("name");
141                o[item_count] = new Observable;
142                if(oName)
143            o[item_count]->name = oName;
144               
145                affect_count = 0;
146                for(pSecondChild = pChild->FirstChildElement("affect"); pSecondChild; \
147                pSecondChild = pSecondChild->NextSiblingElement()) {
148
149                        const char *oUtilName = pSecondChild->Attribute("utility");
150                        if(oUtilName) {
151                                for(attribute_count = 0; u[attribute_count] != NULL; attribute_count++ ) {
152                                        if(u[attribute_count]->name == oUtilName) {
153                                                o[item_count]->affection_list[affect_count].u = u[attribute_count];
154
155                                                const char *oRelate = pSecondChild->Attribute("relationship");
156                                                if(oRelate)
157                            o[item_count]->affection_list[affect_count].relation = oRelate;
158
159                                                affect_count++;
160                                                match_found = true;
161                                                break;
162                                        }
163                                }
164                        }
165
166                        if(!match_found) {
167                ERROR(1, "Error: %s: %s is not a valid utility.\n", \
168                        o[item_count]->name.c_str(), oUtilName);
169            }
170            else
171                match_found = false;   
172                }
173
174                o[item_count]->numAffects = affect_count;
175                item_count++;
176        }
177
178        ce_info->numObservables = item_count;   
179        LOG("Initialize:: Parsed %d observables.\n", ce_info->numObservables);
180
181        pElem = hRoot.FirstChild("parameters").Element();
182        pChild1 = hRoot.Child("parameters", count).Element();
183       
184        item_count = 0;
185        for(pChild = pChild1->FirstChildElement("parameter"); pChild; \
186            pChild = pChild->NextSiblingElement()) {
187
188                p[item_count] = new Parameter;
189
190                const char *pName = pChild->Attribute("name");
191                if(pName)
192            p[item_count]->name = pName;       
193
194                const char *pUnits = pChild->Attribute("units");
195                if(pUnits)
196            p[item_count]->units = pUnits;
197
198                if(pChild->QueryFloatAttribute("min", &p[item_count]->min) != TIXML_SUCCESS)
199            p[item_count]->min = -1;
200
201                if(pChild->QueryFloatAttribute("max", &p[item_count]->max) != TIXML_SUCCESS)
202            p[item_count]->max = -1;
203
204                if(pChild->QueryFloatAttribute("step", &p[item_count]->step) != TIXML_SUCCESS)
205            p[item_count]->step = -1;
206               
207                affect_count = 0;
208                for(pSecondChild = pChild->FirstChildElement("affect"); pSecondChild; \
209                pSecondChild = pSecondChild->NextSiblingElement()) {
210
211                        const char *pUtilName = pSecondChild->Attribute("utility");
212                        if(pUtilName) {
213                                for(attribute_count = 0; u[attribute_count] != NULL; attribute_count++) {
214                                        if(u[attribute_count]->name == pUtilName) {
215                                                p[item_count]->affection_list[affect_count].u = u[attribute_count];     
216
217                                                const char *pRelate = pSecondChild->Attribute("relationship");
218                                                if(pRelate)
219                                                        p[item_count]->affection_list[affect_count].relation = pRelate;
220                                                else
221                                                        LOG("Error: No relation found.\n");
222
223                                                match_found = true;
224                                                affect_count++;
225                                                break;
226                                        }
227                                }
228                        }
229
230                        if(!match_found) {
231                ERROR(1, "Error: %s: %s is not a valid utility.\n", \
232                        p[item_count]->name.c_str(), pUtilName);
233            }
234
235                        match_found = false;   
236                }
237
238                p[item_count]->numAffects = affect_count;
239                item_count++;
240        }
241
242        ce_info->numParameters = item_count;
243        LOG("Initialize:: Parsed %d parameters.\n", ce_info->numParameters);
244
245        return 1;
246}
247
248
249void
250LoadCEConfiguration(int32_t socketfd,Utility* uList[], Parameter* pList[], \
251        Observable* oList[], CE_Info* ce_info)
252{
253        int32_t n,i,j;
254        char counter[55];
255        char var[50];
256        //int32_t total_bytes;   
257
258        printf("Cognitive Radio:: Sending Radio Operating Profile to Cognitive Engine.\n\n");
259 
260        // utilities
261        // Send number of utilities
262        sprintf(counter,"%d",ce_info->numUtilities);
263        SendMessage(socketfd,counter);
264        // send utility
265    for(i = 0; i < ce_info->numUtilities; i++) {
266                SendMessage(socketfd, uList[i]->name.c_str());
267                SendMessage(socketfd, uList[i]->units.c_str());
268                SendMessage(socketfd, uList[i]->goal.c_str());
269                sprintf(var,"%f", uList[i]->target);
270                SendMessage(socketfd,var);
271        }
272
273        // parameters
274    sprintf(counter,"%i",ce_info->numParameters);
275        SendMessage(socketfd,counter);
276        for(i = 0; i < ce_info->numParameters; i++) {
277                SendMessage(socketfd,pList[i]->name.c_str());
278                SendMessage(socketfd,pList[i]->units.c_str());
279                sprintf(var,"%f",pList[i]->min);
280                SendMessage(socketfd,var);
281                sprintf(var,"%f",pList[i]->max);
282                SendMessage(socketfd,var);
283                sprintf(var,"%f",pList[i]->step);
284                SendMessage(socketfd,var);
285               
286                sprintf(counter,"%i",pList[i]->numAffects);
287                SendMessage(socketfd,counter);
288                for(j = 0; j < pList[i]->numAffects; j++) {
289                        SendMessage(socketfd,pList[i]->affection_list[j].u->name.c_str());
290                        SendMessage(socketfd,pList[i]->affection_list[j].relation.c_str());
291                }
292        }
293
294    // observables
295        sprintf(counter,"%i",ce_info->numObservables);
296        SendMessage(socketfd,counter);
297        for(i = 0; i < ce_info->numObservables; i++) {
298                SendMessage(socketfd,oList[i]->name.c_str());
299               
300                sprintf(counter,"%i",oList[i]->numAffects);
301                SendMessage(socketfd,counter);
302                for(j = 0; j < oList[i]->numAffects; j++) {
303                        SendMessage(socketfd,oList[i]->affection_list[j].u->name.c_str());
304                        SendMessage(socketfd,oList[i]->affection_list[j].relation.c_str());
305                }
306        }
307       
308        // Receive ACK for utils
309    char buffer[256];
310        string message;
311        ReadMessage(socketfd, buffer);
312    //printf("%s\n", buffer);
313        //cout << message << endl;
314        //printf("ACK received.\n");
315
316}
317
318
319void
320UpdateCEExperience(int32_t socketfd, int32_t num_rows, int32_t num_cols,
321        float * past_exp[])
322{
323    int32_t i, j;
324        char counter[55];
325        char var[50];
326
327    for (i = 0; i < num_rows; i++){
328        for (j = 0; j< num_cols; j++){
329                sprintf(var,"%f",past_exp[i][j]);
330        //printf("%f, \n", past_exp[i][j]);
331        //printf("%s, \n", var);
332        }
333    }
334   
335    // send the number of rows to the ce first
336        sprintf(counter,"%d",num_rows);
337        SendMessage(socketfd,counter);
338    // send the number of columns to the ce
339        sprintf(counter,"%d",num_cols);
340        SendMessage(socketfd,counter);
341    // update ce with experience
342    for (i = 0; i < num_rows; i++){
343        for (j = 0; j< num_cols; j++){
344                sprintf(var,"%f",past_exp[i][j]);
345                SendMessage(socketfd,var);
346        }
347    }
348
349}
350
351
352int32_t
353RequestPolicyValidation(Parameter * pList[], CE_Info *ce_info)
354{
355        char counter[55];
356        char var[50];
357    int32_t i;
358    char* control_msg = "val";
359   
360    int32_t socketfd = ce_info->policy_socket;
361
362    // Control message that validation request is coming
363        SendMessage(socketfd,control_msg);
364
365    printf("Cognitive Radio:: Here. %i\n\n", socketfd);
366
367        // Send parameter information
368    sprintf(counter,"%i",ce_info->numParameters);
369        SendMessage(socketfd,counter);
370        for(i = 0; i < ce_info->numParameters; i++) {
371                SendMessage(socketfd,pList[i]->name.c_str());
372                SendMessage(socketfd,pList[i]->units.c_str());
373                sprintf(var,"%f",pList[i]->min);
374                SendMessage(socketfd,var);
375                sprintf(var,"%f",pList[i]->max);
376                SendMessage(socketfd,var);
377                sprintf(var,"%f",pList[i]->step);
378                SendMessage(socketfd,var);
379                sprintf(var,"%f",pList[i]->value);
380                SendMessage(socketfd,var);
381               
382        }
383    return 1;
384
385}
386
387
388int32_t
389RequestCEOptimization(int32_t sockfd, Utility *uList[],
390        Parameter *pList[], Observable *oList[],
391        CE_Info *ce_info)
392{
393    char buffer[256];
394    int32_t i;
395    float var;
396
397    // Send request optimization message followed by the current environment parameters.
398    /*
399    SendMessage(sockfd,"request");
400    for (i = 0; i < ce_info->numObservables; i++){
401        SendMessage(sockfd,..);
402    }
403    */
404
405    // Receive optimized values from the Cognitive Engine
406    for (i = 0; i < ce_info->numParameters; i++){
407        bzero(buffer,256);
408        ReadMessage(sockfd,buffer);
409        var = atof(buffer);
410        pList[i]->value = var;
411    }
412
413
414    // If policy engine is connect, validate new values
415    if(ce_info->policy_engine == 1) {
416
417        printf("Cognitive Radio:: Found Policy Engine!\n");
418        printf("Cognitive Radio:: Validating parameters with Policy Engine\n\n");
419        RequestPolicyValidation(pList,ce_info);
420        printf("Cognitive Radio:: Done\n\n");
421
422    }
423
424
425    return 1;
426}
427
428void
429RunSimulator(int32_t socketfd, Utility * uList[],
430        Parameter * pList[], Observable * oList[],
431        CE_Info * ce_info) {
432       
433        float **past_exp;
434    int32_t num_rows, num_cols;
435
436        // Set fake current environment params = current environment
437        RequestCEOptimization(socketfd, uList, pList, oList, ce_info);
438
439        // Act like we are updating the hardware tranmission settings
440        UpdateRadioSettings();
441
442        // Send back fake utility values
443    // need to initialize
444        //UpdateCEExperience(socketfd, num_rows, num_cols, past_exp);   
445}
446
447void
448InitializePE(int32_t socket, CE_Info * ce_info)
449{
450    // Policy Engine is connected
451    // Set global policy engine value to 1
452    ce_info->policy_engine = 1;
453    ce_info->policy_socket = socket;
454
455    return;
456}
457
458void
459InitializeCE(int32_t socketfd, Utility* uList[], Parameter* pList[], \
460        Observable* oList[], CE_Info* ce_info)
461{
462        LoadCEConfiguration(socketfd, uList, pList, oList, ce_info);
463       
464    // cr experience
465    float **past_exp;
466        int32_t num_cols;
467    // get number of columns
468    num_cols = ce_info->numUtilities + ce_info->numParameters;
469    num_cols = num_cols + ce_info->numObservables;
470    num_cols = num_cols + 1;    // overall utility
471    int32_t num_rows = 2;
472    past_exp = (float **)malloc(sizeof(float)*num_rows);
473    int32_t i;
474    for (i=0; i<num_rows; i++){
475        past_exp[i] = (float*)malloc(sizeof(float)*num_cols);
476    }
477    // sample experience #1
478    past_exp[0][0] = 1e3f;  // throughput
479    past_exp[0][1] = 1;     // spectral_efficiency
480    past_exp[0][2] = -3.5;  // log10_ber
481    past_exp[0][3] = 1;     // mod_scheme
482    past_exp[0][4] = -10;   // tx_power
483    past_exp[0][5] = 10.0;  // SNR
484    past_exp[0][6] = 0.762; // overall utility*/
485    // sample experience #2
486    past_exp[1][0] = 1e2f;  // throughput
487    past_exp[1][1] = 1;     // spectral_efficiency
488    past_exp[1][2] = -3.5;  // log10_ber
489    past_exp[1][3] = 1;     // mod_scheme
490    past_exp[1][4] = -14;   // tx_power
491    past_exp[1][5] = 3.0;   // SNR
492    past_exp[1][6] = 0.462; // overall utility
493
494        // update ce with experience
495    printf("Cognitive Radio:: Sending Previous Experience to New Cognitive Engine.\n\n");
496    UpdateCEExperience(socketfd, num_rows, num_cols, past_exp);
497
498        RunSimulator(socketfd, uList, pList, oList, ce_info);
499}
500
501
502int32_t
503StartServers(Utility* uList[], Parameter* pList[], Observable* oList[], \
504        CE_Info* ce_info)
505{
506    int32_t * servSock;
507    int32_t running = 1;
508    struct timeval selTimeout;
509    int32_t timeout = 10;
510    int32_t cognitive_engine = 0;
511    int32_t policy_engine = 1;
512    int32_t port, rc, on = 1;
513    int32_t new_sd;
514    int32_t desc_ready = 0;
515    fd_set sockSet;
516   
517    servSock = (int32_t *) malloc(2 * sizeof(int32_t));
518
519    servSock[cognitive_engine] = CreateTCPServerSocket(CE_SERVER_PORT);
520    servSock[policy_engine] = CreateTCPServerSocket(PE_SERVER_PORT);
521
522
523    int32_t maxDescriptor = servSock[cognitive_engine];
524
525    if(servSock[cognitive_engine] < servSock[policy_engine])
526        maxDescriptor = servSock[policy_engine];
527
528    rc = setsockopt(servSock[cognitive_engine], SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
529    if(rc < 0)
530    {
531        perror("setsockopt() failed");
532        close(servSock[cognitive_engine]);
533        exit(-1);
534    }
535   
536    rc = setsockopt(servSock[policy_engine], SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
537    if(rc < 0)
538    {
539        perror("setsockopt() failed");
540        close(servSock[policy_engine]);
541        exit(-1);
542    }
543   
544    rc = ioctl(servSock[cognitive_engine], FIONBIO, (char*)&on);
545    if(rc < 0)
546    {
547        perror("ioctl() failed");
548        close(servSock[cognitive_engine]);
549        exit(-1);
550    }
551   
552    rc = ioctl(servSock[policy_engine], FIONBIO, (char*)&on);
553    if(rc < 0)
554    {
555        perror("ioctl() failed");
556        close(servSock[policy_engine]);
557        exit(-1);
558    }
559   
560    printf("Starting server:  Hit return to shutdown\n");
561    while (running)
562    {
563        /* Zero socket descriptor vector and set for server sockets */
564        /* This must be reset every time select() is called */
565        FD_ZERO(&sockSet);
566        /* Add keyboard to descriptor vector */
567        FD_SET(STDIN_FILENO, &sockSet);
568        FD_SET(servSock[cognitive_engine], &sockSet);
569        FD_SET(servSock[policy_engine], &sockSet);
570
571        /* Timeout specification */
572        /* This must be reset every time select() is called */
573        selTimeout.tv_sec = timeout;       /* timeout (secs.) */
574        selTimeout.tv_usec = 0;            /* 0 microseconds */
575
576        /* Suspend program until descriptor is ready or timeout */
577        rc = select(maxDescriptor + 1, &sockSet, NULL, NULL, &selTimeout);
578        if (rc == 0)
579            printf("No echo requests for %i secs...Server still alive\n", timeout);
580        else
581        {
582            if (FD_ISSET(0, &sockSet)) /* Check keyboard */
583            {
584                printf("Shutting down server\n");
585                getchar();
586                running = 0;
587            }
588
589            desc_ready = rc;
590
591            for (port = 0; port <= maxDescriptor && desc_ready > 0; port++) {
592                if (FD_ISSET(port, &sockSet))
593                {
594                    printf("Request on port %d:  ", port);
595                        desc_ready -= 1;
596
597
598                    if( (port == servSock[cognitive_engine]) || (port == servSock[policy_engine])) {
599                       
600                        do
601                        {
602                            new_sd = AcceptTCPConnection(port);
603                            if(new_sd < 0)
604                            {
605                                break;
606                            }
607                           
608                            HandleTCPClient(new_sd, uList, pList, oList, ce_info);
609                            FD_SET(new_sd,&sockSet);
610                            if(new_sd > maxDescriptor)
611                                maxDescriptor = new_sd;
612                            printf("New incoming connection - %i\n\n",new_sd);
613                        } while(new_sd != -1);
614                    } else {
615                       
616                        printf("Request on already open descriptor.\n\n");
617                        HandleTCPClient(port, uList, pList, oList, ce_info);
618
619                    }
620
621                }
622            }
623        }
624    }
625
626    /* Close sockets */
627    for (port = 0; port < 2; port++)
628        close(servSock[port]);
629
630    /* Free list of sockets */
631    free(servSock);       
632       
633        return 0;
634}
635
636int32_t
637main(int32_t argc, char* argv[])
638{
639        // CognitiveEngine CE;
640        // CognitiveEngineShell Shell;
641        string pFilename;
642    int32_t fd;
643
644        Utility * uList[10];
645        Parameter * pList[10];
646        Observable * oList[10];
647        struct CE_Info *ce_info;
648
649    if((fd = open("/dev/zero", O_RDWR)) == -1)
650            return 1;
651
652    ce_info = (struct CE_Info *)mmap(0,sizeof(CE_Info),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
653
654    close(fd);
655
656        if(argc < 2) {
657                cout << "Warning no XML file specific using default: example.xml" << endl;
658                pFilename = "example.xml";
659        } else { 
660                pFilename = argv[1];
661        }
662
663        TiXmlDocument doc( pFilename.c_str() );
664        bool loadOkay = doc.LoadFile();
665        if (!loadOkay)
666        {
667                cout << "Loading " << pFilename << " failed." << endl;
668                return 0;
669        }
670
671        cout << "\n\nInitialize:: Attemping to parse " << pFilename << "." << endl;
672        parse_ce_config( &doc , uList, pList, oList, ce_info);
673        cout << "Initialize:: Configuration file parsing completed.\n" << endl;
674
675    //print_current_config(uList, pList, oList, &ce_info);
676       
677   StartServers(uList, pList, oList, ce_info);
678   return 1;
679}
Note: See TracBrowser for help on using the browser.