/* Virginia Tech Cognitive Radio Open Source Systems * Virginia Tech, 2009 * * TODO LICENSE INFORMATION GOES HERE */ /* TODO DESCRIPTION OF FILE. */ #include #include #include #include #include #include #include #include #include #include #include "tinyxml/tinyxml.h" #include "tinyxml/tinystr.h" #include "vtcross/common.h" #include "vtcross/components.h" #include "vtcross/containers.h" #include "vtcross/debug.h" #include "vtcross/error.h" #include "vtcross/socketcomm.h" using namespace std; #define CE_SERVER_PORT 30001 #define PE_SERVER_PORT 30003 void print_current_config(Utility* uList[], Parameter* pList[], \ Observable* oList[], CE_Info* ce_info) { for(size_t i = 0; i < ce_info->numUtilities ; i++) { LOG("Shell:: Utility: %s\n\tUnits: %s\n\tGoal: %s\n\tTarget: %s\n", \ uList[i]->name, uList[i]->units, uList[i]->goal, \ uList[i]->target); } for(size_t i = 0; i < ce_info->numParameters; i++) { LOG("Shell:: Radio Operation Profile has been sucessfully sent.\n"); LOG("Shell:: Parameter: %s\n\tUnits: %s\n\tMin: %s\n\t", \ pList[i]->name, pList[i]->units, pList[i]->min); LOG("\tMax: %s\n\tStep: %s\n", pList[i]->max, pList[i]->step); for(size_t j = 0; j < pList[i]->numAffects; j++) { LOG("\t\tAffect %s -> %s\n", pList[i]->affection_list[j].u->name, \ pList[i]->affection_list[j].relation); } } for(size_t i = 0; i < ce_info->numObservables; i++) { LOG("Observable: %s\n", oList[i]->name); for(size_t j = 0; j < oList[i]->numAffects; j++) { LOG("\t\tAffect %s -> %s ", oList[i]->affection_list[j].u->name, \ oList[i]->affection_list[j].relation); } } } int32_t parse_ce_config(TiXmlDocument* doc, Utility* u[], Parameter* p[], \ Observable* o[], CE_Info* ce_info) { TiXmlElement* pElem; //!current element TiXmlElement* pChild; //!current child of pElem TiXmlElement* pChild1; //!current child of pElem TiXmlElement* pSecondChild; //!current child of pElem TiXmlHandle hDoc(doc); //!handle to xml document TiXmlHandle hRoot(0); //! handle to root element int32_t count = 0; int32_t i = 0; int32_t j = 0; int32_t k = 0; int32_t match_found = 0; pElem = hDoc.FirstChildElement().Element(); if(!pElem) { cout << "no valid root! quit-ing function!" << endl; return 0; } hRoot = TiXmlHandle(pElem); // Pull utility information from XML file. pElem = hRoot.FirstChild("utilities").Element(); pChild1 = hRoot.Child("utilities",count).Element(); for(pChild = pChild1->FirstChildElement("utility"); pChild; pChild = pChild->NextSiblingElement()) { u[i] = new Utility; const char *uName = pChild->Attribute("name"); if(uName) u[i]->name = uName; const char *uUnits = pChild->Attribute("units"); if(uUnits) u[i]->units = uUnits; const char *uGoal = pChild->Attribute("goal"); if(uGoal) u[i]->goal = uGoal; if(pChild->QueryFloatAttribute("target",&u[i]->target) != TIXML_SUCCESS) u[i]->target = -1; i++; } ce_info->numUtilities = i; cout << "Initialize:: Parsed " << ce_info->numUtilities << " utilities." << endl; // Pull observable information from XML file. i = 0; pElem = hRoot.FirstChild("observables").Element(); pChild1 = hRoot.Child("observables",count).Element(); for(pChild = pChild1->FirstChildElement("observable"); pChild; pChild = pChild->NextSiblingElement()) { const char *oName = pChild->Attribute("name"); o[i] = new Observable; if(oName) o[i]->name = oName; j = 0; for(pSecondChild = pChild->FirstChildElement("affect"); pSecondChild; pSecondChild = pSecondChild->NextSiblingElement()) { const char *oUtilName = pSecondChild->Attribute("utility"); // If a utility affects this parameter find the utility object and assign it if(oUtilName) { // Search for correct utility for( k=0 ; u[k]!=NULL ; k++ ){ if(u[k]->name == oUtilName) { o[i]->affection_list[j].u = u[k]; // Set relationship const char *oRelate = pSecondChild->Attribute("relationship"); if(oRelate) o[i]->affection_list[j].relation = oRelate; j++; match_found = 1; break; } } } if(!match_found) cout << "Error: " << o[i]->name << ": " << oUtilName << " not a valid utility: Affect not added." << endl; match_found = 0; } o[i]->numAffects = j; i++; } ce_info->numObservables = i; cout << "Initialize:: Parsed " << ce_info->numObservables << " observables." << endl; // Pull parameter information from XML file. pElem = hRoot.FirstChild("parameters").Element(); pChild1 = hRoot.Child("parameters",count).Element(); i = 0; for(pChild = pChild1->FirstChildElement("parameter"); pChild; pChild = pChild->NextSiblingElement()) { p[i] = new Parameter; const char *pName = pChild->Attribute("name"); if(pName) p[i]->name = pName; const char *pUnits = pChild->Attribute("units"); if(pUnits) p[i]->units = pUnits; if(pChild->QueryFloatAttribute("min",&p[i]->min) != TIXML_SUCCESS) p[i]->min = -1; if(pChild->QueryFloatAttribute("max",&p[i]->max) != TIXML_SUCCESS) p[i]->max = -1; if(pChild->QueryFloatAttribute("step",&p[i]->step) != TIXML_SUCCESS) p[i]->step = -1; j = 0; for(pSecondChild = pChild->FirstChildElement("affect"); pSecondChild; pSecondChild = pSecondChild->NextSiblingElement()) { const char *pUtilName = pSecondChild->Attribute("utility"); // If a utility affects this parameter find the utility object and assign it if(pUtilName) { // Search for correct utility for( k=0 ; u[k]!=NULL ; k++ ){ if(u[k]->name == pUtilName) { // If match found, assign it to this index p[i]->affection_list[j].u = u[k]; const char *pRelate = pSecondChild->Attribute("relationship"); if(pRelate) { p[i]->affection_list[j].relation = pRelate; } else { cout << "Error: No relation found." << endl; } match_found = 1; j++; break; } } } if(!match_found) cout << "Error: " << p[i]->name << ": " << pUtilName << " not a valid utility: Affect not added." << endl; match_found = 0; } p[i]->numAffects = j; i++; } ce_info->numParameters = i; cout << "Initialize:: Parsed " << ce_info->numParameters << " parameters." << endl; return 1; } int32_t ReceiveMessage(int32_t socket, char* buffer) { int32_t i,n; n = recv(socket,buffer,256,MSG_PEEK); for(i=0;i<256;i++){ if(strcmp(&buffer[i],"\0") == 0) break; } n = recv(socket,buffer,i+1,0); if (n < 0) error("ERROR reading from socket"); // print32_tf("ReadMessage:%s %d\n",buffer,n); return n; } int32_t SendMessage(int32_t socketfd, string message) { int32_t n; message.append("\0"); // Write message back to client n = send(socketfd,message.c_str(),(message.size()+1),0); if (n<0) error("Error sending to client\n"); if(n == 0) print32_tf("Client closed the socket.\n"); //print32_tf("SendMessage:%s %d\n",message.c_str(),n); return n; } void LoadCEConfiguration(int32_t socketfd,Utility * uList[], Parameter * pList[], Observable * oList[], CE_Info * ce_info){ int32_t n,i,j; char counter[55]; char var[50]; //int32_t total_bytes; print32_tf("Cognitive Radio:: Sending Radio Operating Profile to Cognitive Engine.\n\n"); // utilities // Send number of utilities sprint32_tf(counter,"%d",ce_info->numUtilities); SendMessage(socketfd,counter); // send utility for(i = 0; i < ce_info->numUtilities; i++) { SendMessage(socketfd,uList[i]->name); SendMessage(socketfd,uList[i]->units); SendMessage(socketfd,uList[i]->goal); sprint32_tf(var,"%f",uList[i]->target); SendMessage(socketfd,var); } // parameters sprint32_tf(counter,"%i",ce_info->numParameters); SendMessage(socketfd,counter); for(i = 0; i < ce_info->numParameters; i++) { SendMessage(socketfd,pList[i]->name); SendMessage(socketfd,pList[i]->units); sprint32_tf(var,"%f",pList[i]->min); SendMessage(socketfd,var); sprint32_tf(var,"%f",pList[i]->max); SendMessage(socketfd,var); sprint32_tf(var,"%f",pList[i]->step); SendMessage(socketfd,var); sprint32_tf(counter,"%i",pList[i]->numAffects); SendMessage(socketfd,counter); for(j = 0; j < pList[i]->numAffects; j++) { SendMessage(socketfd,pList[i]->affection_list[j].u->name); SendMessage(socketfd,pList[i]->affection_list[j].relation); } } // observables sprint32_tf(counter,"%i",ce_info->numObservables); SendMessage(socketfd,counter); for(i = 0; i < ce_info->numObservables; i++) { SendMessage(socketfd,oList[i]->name); sprint32_tf(counter,"%i",oList[i]->numAffects); SendMessage(socketfd,counter); for(j = 0; j < oList[i]->numAffects; j++) { SendMessage(socketfd,oList[i]->affection_list[j].u->name); SendMessage(socketfd,oList[i]->affection_list[j].relation); } } // Receive ACK for utils char buffer[256]; string message; n = ReceiveMessage(socketfd, buffer); //print32_tf("%s\n", buffer); //cout << message << endl; //print32_tf("ACK received.\n"); } void UpdateCEConfiguration() { } void ResetCEConfiguration(){ } void UpdateCEExperience(int32_t socketfd, int32_t num_rows, int32_t num_cols, float * past_exp[]) { int32_t i, j; char counter[55]; char var[50]; for (i = 0; i < num_rows; i++){ for (j = 0; j< num_cols; j++){ sprint32_tf(var,"%f",past_exp[i][j]); //print32_tf("%f, \n", past_exp[i][j]); //print32_tf("%s, \n", var); } } // send the number of rows to the ce first sprint32_tf(counter,"%d",num_rows); SendMessage(socketfd,counter); // send the number of columns to the ce sprint32_tf(counter,"%d",num_cols); SendMessage(socketfd,counter); // update ce with experience for (i = 0; i < num_rows; i++){ for (j = 0; j< num_cols; j++){ sprint32_tf(var,"%f",past_exp[i][j]); SendMessage(socketfd,var); } } } void ResetCEExperience() { } // Update operating settings // This function will int32_teract with the hardware "drivers" void UpdateRadioSettings() { } int32_t RequestPolicyValidation(Parameter * pList[], CE_Info *ce_info) { char counter[55]; char var[50]; int32_t i; string control_msg; int32_t socketfd = ce_info->policy_socket; // Control message that validation request is coming control_msg = "val"; SendMessage(socketfd,control_msg); print32_tf("Cognitive Radio:: Here. %i\n\n", socketfd); // Send parameter information sprint32_tf(counter,"%i",ce_info->numParameters); SendMessage(socketfd,counter); for(i = 0; i < ce_info->numParameters; i++) { SendMessage(socketfd,pList[i]->name); SendMessage(socketfd,pList[i]->units); sprint32_tf(var,"%f",pList[i]->min); SendMessage(socketfd,var); sprint32_tf(var,"%f",pList[i]->max); SendMessage(socketfd,var); sprint32_tf(var,"%f",pList[i]->step); SendMessage(socketfd,var); sprint32_tf(var,"%f",pList[i]->value); SendMessage(socketfd,var); } return 1; } int32_t RequestCEOptimization(int32_t sockfd, Utility *uList[], Parameter *pList[], Observable *oList[], CE_Info *ce_info) { char buffer[256]; int32_t i; float var; // Send request optimization message followed by the current environment parameters. /* SendMessage(sockfd,"request"); for (i = 0; i < ce_info->numObservables; i++){ SendMessage(sockfd,..); } */ // Receive optimized values from the Cognitive Engine for (i = 0; i < ce_info->numParameters; i++){ bzero(buffer,256); ReceiveMessage(sockfd,buffer); var = atof(buffer); pList[i]->value = var; } // If policy engine is connect, validate new values if(ce_info->policy_engine == 1) { print32_tf("Cognitive Radio:: Found Policy Engine!\n"); print32_tf("Cognitive Radio:: Validating parameters with Policy Engine\n\n"); RequestPolicyValidation(pList,ce_info); print32_tf("Cognitive Radio:: Done\n\n"); } return 1; } void RunSimulator(int32_t socketfd, Utility * uList[], Parameter * pList[], Observable * oList[], CE_Info * ce_info) { float **past_exp; int32_t num_rows, num_cols; // Set fake current environment params = current environment RequestCEOptimization(socketfd, uList, pList, oList, ce_info); // Act like we are updating the hardware tranmission settings UpdateRadioSettings(); // Send back fake utility values // need to initialize //UpdateCEExperience(socketfd, num_rows, num_cols, past_exp); } void InitializePE(int32_t socket, CE_Info * ce_info) { // Policy Engine is connected // Set global policy engine value to 1 ce_info->policy_engine = 1; ce_info->policy_socket = socket; return; } void InitializeCE(int32_t socketfd, Utility * uList[], Parameter * pList[], Observable * oList[], CE_Info * ce_info) { LoadCEConfiguration(socketfd, uList, pList, oList, ce_info); // cr experience float **past_exp; int32_t num_cols; // get number of columns num_cols = ce_info->numUtilities + ce_info->numParameters; num_cols = num_cols + ce_info->numObservables; num_cols = num_cols + 1; // overall utility int32_t num_rows = 2; past_exp = (float **)malloc(sizeof(float)*num_rows); int32_t i; for (i=0; i 0; port++) { if (FD_ISSET(port, &sockSet)) { print32_tf("Request on port %d: ", port); desc_ready -= 1; if( (port == servSock[cognitive_engine]) || (port == servSock[policy_engine])) { do { new_sd = AcceptTCPConnection(port); if(new_sd < 0) { break; } HandleTCPClient(new_sd, uList, pList, oList, ce_info); FD_SET(new_sd,&sockSet); if(new_sd > maxDescriptor) maxDescriptor = new_sd; print32_tf("New incoming connection - %i\n\n",new_sd); } while(new_sd != -1); } else { print32_tf("Request on already open descriptor.\n\n"); HandleTCPClient(port, uList, pList, oList, ce_info); } } } } } /* Close sockets */ for (port = 0; port < 2; port++) close(servSock[port]); /* Free list of sockets */ free(servSock); return 0; } int32_t main(int32_t argc, char* argv[]) { // CognitiveEngine CE; // CognitiveEngineShell Shell; string pFilename; int32_t fd; Utility * uList[10]; Parameter * pList[10]; Observable * oList[10]; struct CE_Info *ce_info; if((fd = open("/dev/zero", O_RDWR)) == -1) return 1; ce_info = (struct CE_Info *)mmap(0,sizeof(CE_Info),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); close(fd); if(argc < 2) { cout << "Warning no XML file specific using default: example.xml" << endl; pFilename = "example.xml"; } else { pFilename = argv[1]; } TiXmlDocument doc( pFilename.c_str() ); bool loadOkay = doc.LoadFile(); if (!loadOkay) { cout << "Loading " << pFilename << " failed." << endl; return 0; } cout << "\n\nInitialize:: Attemping to parse " << pFilename << "." << endl; parse_ce_config( &doc , uList, pList, oList, ce_info); cout << "Initialize:: Configuration file parsing completed.\n" << endl; //print32_t_current_config(uList, pList, oList, &ce_info); StartServers(uList, pList, oList, ce_info); return 1; }