#include "BehaviorManager.hh" BehaviorManager::BehaviorManager (int serverPort) { runServer = false; this->serverPort = serverPort; cout << "BehaviorManager: Set server port to " << serverPort << endl; runServer = initalizeNetworking(); cout << "BehaviorManager: Initialized networking (" << runServer << ")" << endl; } BehaviorManager::~BehaviorManager() { /* nothing to do */ } bool BehaviorManager::initalizeNetworking() { clientServer = socket (AF_INET, SOCK_STREAM, 0); if (clientServer < 0) { cerr << "Error creating server socket. Exiting." << endl; exit(1); return false; } bzero (&ClientServerAddress, sizeof(ClientServerAddress)); ClientServerAddress.sin_family = AF_INET; ClientServerAddress.sin_port = htons (serverPort); ClientServerAddress.sin_addr.s_addr = INADDR_ANY; ClientServerAddressLength = sizeof (ClientServerAddress); ClientAddressLength = sizeof (ClientAddress); if (bind (clientServer, (struct sockaddr*)&ClientServerAddress, ClientServerAddressLength) < 0) { cout << "BehaviorManager: Error binding to server socket. Exiting." << endl; return false; } if (listen (clientServer, 20) < 0) { cout << "BehaviorManager: Error listening on server socket. Exiting." << endl; return false; } return true; } void* BehaviorManager::startServer (void* arg) { BehaviorManager* behManager = (BehaviorManager*)arg; while ( behManager->runServer ) { // cout << "BehaviorManager: waiting for a client." << endl; behManager->clientSocket = accept (behManager->clientServer, (struct sockaddr*)&behManager->ClientServerAddress, &behManager->ClientServerAddressLength); if (behManager->clientSocket < 0) { cout << "BehaviorManager: Error accepting a connection." << endl; behManager->runServer = false; break; } // cout << "BehaviorManager: got a connection" << endl; int level, id, command; Semaphore* sem; char* hostname; if (getpeername (behManager->clientSocket, (struct sockaddr*)&behManager->ClientServerAddress, &behManager->ClientServerAddressLength) < 0) { cout << "BehaviorManager: Error getting peer name." << endl; cout << "addrLength = " << behManager->ClientServerAddressLength << " (" << sizeof (struct sockaddr_in) << ")" << endl; hostname = "i.dont.know"; } else { hostname = inet_ntoa (behManager->ClientServerAddress.sin_addr); } read (behManager->clientSocket, &level, sizeof (level)); read (behManager->clientSocket, &id, sizeof (id)); read (behManager->clientSocket, &command, sizeof (command)); if (command == REGISTER) { int add; read (behManager->clientSocket, &add, sizeof (&add)); sem = (Semaphore*)add; } /* cout << "BehaviorManager: got (level,id,command,hostname) = (" << level << "," << id << "," << command << "," << hostname << ")" << endl; */ switch (command) { case REGISTER: behManager->registerBehavior (level, id, hostname, sem); break; case SUSPEND: behManager->suspend (level); break; case RESUME: behManager->resume (level); break; case TESTSUSPEND: behManager->testSuspend (level, id); break; } close (behManager->clientSocket); } return NULL; } /** * void* BehaviorManager::serverThread (void* arg) * * This method is the one that gets called to accept a connection from * a behavior. It's in a separate thread so that the server can accept * a reasonable number of connections at "once". */ //void* //BehaviorManager::serverThread (void* arg) //{ // //} /* * ##TODO: Since multiple behaviors can have the same level and id but * different hostnames, register and unregister need to check _ALL_ of the * pairs when checking to see if a behavior exists in the dbase. * Actually, to get around this and also to allow behaviors to be public or * private (and also maybe have ACLs in the future), when a behavior is * registered, it should be given a unique ID based on hostname, level and * levelID. Then life will be easier ... */ void BehaviorManager::registerBehavior (int level, int ID, char* hostname, Semaphore* sem) { map::iterator i = levels.find (level); if (i == levels.end ()) { // this level hasn't been made yet ... create it priorityLevelStruct* newLevel = new priorityLevelStruct[1]; newLevel->numBehaviors = 1; newLevel->levelNumber = level; newLevel->levelSuspensions = 0; newLevel->IDs.push_back (ID); newLevel->pendingSuspend.insert (pair (ID, 0)); newLevel->hostnames.insert (pair (ID, hostname)); newLevel->sems.insert (pair (ID, sem)); levels.insert (pair (level, newLevel)); } else { // otherwise just update the priorityLevelStruct - need to make // sure that a behavior with the same ID doesn't already exist // from the same server map::iterator j = i->second->hostnames.find (ID); if (j == i->second->hostnames.end () || j->second != hostname) // this ID doesn't already exist ... go // ahead and insert it { int suspensions = i->second->levelSuspensions; i->second->numBehaviors++; i->second->IDs.push_back (ID); i->second->pendingSuspend.insert (pair (ID, suspensions)); i->second->hostnames.insert (pair (ID, hostname)); i->second->sems.insert (pair (ID, sem)); } else { // this ID was already in the dbase - complain // and then don't worry about it cerr << "BehaviorManager: " << ID << " is already registered." << endl; } } } void BehaviorManager::unregisterBehavior (int level, int ID, char* hostname) { map::iterator i = levels.find (level); if (i != levels.end ()) { map ::iterator j = i->second->hostnames.find (ID); if (j != i->second->hostnames.end ()) { if (j->second == hostname) { i->second->numBehaviors--; // ditch the ID, pendingSuspend and hostname entries } } } } void BehaviorManager::testSuspend (int level, int ID) { bool suspend = true; map::iterator i = levels.find (level); if (i == levels.end ()) { // this should only happen if a behavior calls testSuspend before // registering itself (or maybe if registration fails and it does not // stop its execution ...) suspend = false; } else { map::iterator suspendID = i->second->pendingSuspend.find (ID); if (suspendID == i->second->pendingSuspend.end ()) { // same thing here ... suspend = false; } else if (suspendID->second <= 0) { /* cout << "BehaviorManager: Behavior #" << ID << " (level=" << level << ") has " << suspendID->second << " outstanding suspensions" << endl; */ suspend = false; } } int int_suspend = 0; if (suspend) { int_suspend = 1; } write (clientSocket, &int_suspend, sizeof (int_suspend)); } void BehaviorManager::suspend (int level) { // cout << "BehaviorManager: Suspending level " << level << endl; map::iterator i = levels.lower_bound (level); if (i == levels.end()) { // cout << "BehaviorManager: No behaviors at level " << level << endl; return; } i++; for (; i != levels.end (); i++) { //cout << "BehaviorManager: Suspending level " << i->first << endl; map::iterator j = i->second->pendingSuspend.begin (); for (; j != i->second->pendingSuspend.end(); j++) { j->second++; } } } void BehaviorManager::resume (int level) { map::iterator i = levels.lower_bound (level); if (i == levels.end ()) { return; } i++; for (; i != levels.end (); i++) { map::iterator j = i->second->pendingSuspend.begin (); for (; j != i->second->pendingSuspend.end (); j++) { j->second--; } map::iterator Sems = i->second->sems.begin (); for (; Sems != i->second->sems.end (); Sems++) { Sems->second->up (); } } /* * ALSO HAVE TO SEND A NOTIFICATION TO THE RESUME BEHAVIOR * AT EACH IP ADDRESS */ }