From 1e05936aead35efad9d1a93e4c9f4b4ae97de053 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Jun 2013 15:19:12 -0700 Subject: [PATCH] unthread DS check in, allow agents to tell DS who they want to hear about --- domain-server/src/main.cpp | 14 +++- interface/src/Application.cpp | 8 +- libraries/shared/src/AgentList.cpp | 120 +++++++++++++++-------------- libraries/shared/src/AgentList.h | 32 ++++---- libraries/shared/src/AgentTypes.h | 15 ++-- 5 files changed, 105 insertions(+), 84 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index b38ae5b824..da4852c4d9 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -102,7 +102,7 @@ int main(int argc, const char * argv[]) std::map newestSoloAgents; agentType = packetData[1]; - unpackSocket(packetData + 2, (sockaddr*) &agentLocalAddress); + int numBytesSocket = unpackSocket(packetData + 2, (sockaddr*) &agentLocalAddress); // check the agent public address // if it matches our local address we're on the same box @@ -124,11 +124,19 @@ int main(int argc, const char * argv[]) agentList->increaseAgentID(); } - currentBufferPos = broadcastPacket + 1; + currentBufferPos = broadcastPacket + sizeof(PACKET_HEADER); startPointer = currentBufferPos; + char* agentTypesOfInterest = (char*) currentBufferPos + sizeof(AGENT_TYPE) + numBytesSocket; + int numInterestTypes = strlen(agentTypesOfInterest); + for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { - if (!agent->matches((sockaddr*) &agentPublicAddress, (sockaddr*) &agentLocalAddress, agentType)) { + if (!agent->matches((sockaddr*) &agentPublicAddress, (sockaddr*) &agentLocalAddress, agentType) + && (numInterestTypes > 0 && memchr(agentTypesOfInterest, agent->getType(), strlen(agentTypesOfInterest)))) { + // this is not the agent themselves + // and this is an agent of a type in the passed agent types of interest + // or the agent did not pass us any specific types they are interested in + if (memchr(SOLO_AGENT_TYPES, agent->getType(), sizeof(SOLO_AGENT_TYPES)) == NULL) { // this is an agent of which there can be multiple, just add them to the packet // don't send avatar agents to other avatars, that will come from avatar mixer diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a0bf0ef705..fe65c56424 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -207,10 +207,13 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : WSADATA WsaData; int wsaresult = WSAStartup(MAKEWORD(2,2), &WsaData); #endif + + // tell the AgentList instance who to tell the domain server we care about + const unsigned char agentTypesOfInterest[] = {AGENT_TYPE_AUDIO_MIXER, AGENT_TYPE_AVATAR_MIXER, AGENT_TYPE_VOXEL_SERVER}; + AgentList::getInstance()->setAgentTypesOfInterest(agentTypesOfInterest, sizeof(agentTypesOfInterest)); // start the agentList threads AgentList::getInstance()->startSilentAgentRemovalThread(); - AgentList::getInstance()->startDomainServerCheckInThread(); AgentList::getInstance()->startPingUnknownAgentsThread(); _window->setCentralWidget(_glWidget); @@ -749,6 +752,9 @@ void Application::timer() { if (!_serialHeadSensor.active) { _serialHeadSensor.pair(); } + + // ask the agent list to check in with the domain server + AgentList::getInstance()->sendDomainServerCheckIn(); } static glm::vec3 getFaceVector(BoxFace face) { diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index 53aad60cd3..982116b39a 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -34,7 +34,6 @@ char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup const int DOMAINSERVER_PORT = 40102; bool silentAgentThreadStopFlag = false; -bool domainServerCheckinStopFlag = false; bool pingUnknownAgentThreadStopFlag = false; AgentList* AgentList::_sharedInstance = NULL; @@ -62,6 +61,7 @@ AgentList::AgentList(char newOwnerType, unsigned int newSocketListenPort) : _numAgents(0), _agentSocket(newSocketListenPort), _ownerType(newOwnerType), + _agentTypesOfInterest(NULL), _socketListenPort(newSocketListenPort), _ownerID(UNKNOWN_AGENT_ID), _lastAgentID(0) { @@ -69,9 +69,10 @@ AgentList::AgentList(char newOwnerType, unsigned int newSocketListenPort) : } AgentList::~AgentList() { + delete _agentTypesOfInterest; + // stop the spawned threads, if they were started stopSilentAgentRemovalThread(); - stopDomainServerCheckInThread(); stopPingUnknownAgentsThread(); pthread_mutex_destroy(&mutex); @@ -177,6 +178,65 @@ Agent* AgentList::agentWithID(uint16_t agentID) { return NULL; } +void AgentList::setAgentTypesOfInterest(const unsigned char* agentTypesOfInterest, int numAgentTypesOfInterest) { + delete _agentTypesOfInterest; + + _agentTypesOfInterest = new unsigned char[numAgentTypesOfInterest + sizeof(char)]; + memcpy(_agentTypesOfInterest, agentTypesOfInterest, numAgentTypesOfInterest); + _agentTypesOfInterest[numAgentTypesOfInterest] = '\0'; +} + +void AgentList::sendDomainServerCheckIn() { + static bool printedDomainServerIP = false; + // Lookup the IP address of the domain server if we need to + if (atoi(DOMAIN_IP) == 0) { + struct hostent* pHostInfo; + if ((pHostInfo = gethostbyname(DOMAIN_HOSTNAME)) != NULL) { + sockaddr_in tempAddress; + memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length); + strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr)); + printLog("Domain Server: %s \n", DOMAIN_HOSTNAME); + } else { + printLog("Failed domain server lookup\n"); + } + } else if (!printedDomainServerIP) { + printLog("Domain Server IP: %s\n", DOMAIN_IP); + printedDomainServerIP = true; + } + + // construct the DS check in packet if we need to + static unsigned char* checkInPacket = NULL; + + if (!checkInPacket) { + int numBytesAgentsOfInterest = _agentTypesOfInterest ? strlen((char*) _agentTypesOfInterest) : NULL; + printf("There are %d AOI\n", numBytesAgentsOfInterest); + // check in packet has header, agent type, port, IP, agent types of interest, null termination + int numPacketBytes = sizeof(PACKET_HEADER) + sizeof(AGENT_TYPE) + sizeof(uint16_t) + (sizeof(char) * 4) + + numBytesAgentsOfInterest + sizeof(char); + printf("Packet as a whole will be %d\n", numPacketBytes); + + checkInPacket = new unsigned char[numPacketBytes]; + + checkInPacket[0] = (memchr(SOLO_AGENT_TYPES, _ownerType, sizeof(SOLO_AGENT_TYPES))) + ? PACKET_HEADER_DOMAIN_REPORT_FOR_DUTY + : PACKET_HEADER_DOMAIN_LIST_REQUEST; + checkInPacket[1] = _ownerType; + + packSocket(checkInPacket + sizeof(PACKET_HEADER) + sizeof(AGENT_TYPE), getLocalAddress(), htons(_socketListenPort)); + + // copy over the bytes for agent types of interest, if required + if (numBytesAgentsOfInterest > 0) { + memcpy(checkInPacket + numPacketBytes - sizeof(char) - numBytesAgentsOfInterest, + _agentTypesOfInterest, + numBytesAgentsOfInterest); + } + + checkInPacket[numPacketBytes - 1] = '\0'; + } + + _agentSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, checkInPacket, strlen((char*) checkInPacket)); +} + int AgentList::processDomainServerList(unsigned char *packetData, size_t dataBytes) { int readAgents = 0; @@ -388,62 +448,6 @@ void AgentList::stopSilentAgentRemovalThread() { pthread_join(removeSilentAgentsThread, NULL); } -void *checkInWithDomainServer(void *args) { - - const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000; - - // Lookup the IP address of the domain server if we need to - if (atoi(DOMAIN_IP) == 0) { - struct hostent* pHostInfo; - if ((pHostInfo = gethostbyname(DOMAIN_HOSTNAME)) != NULL) { - sockaddr_in tempAddress; - memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length); - strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr)); - printLog("Domain Server: %s \n", DOMAIN_HOSTNAME); - - } else { - printLog("Failed lookup domainserver\n"); - } - } else printLog("Domain Server IP: %s\n", DOMAIN_IP); - - AgentList* parentAgentList = (AgentList*) args; - - timeval lastSend; - in_addr_t localAddress = getLocalAddress(); - unsigned char packet[8]; - - packet[0] = PACKET_HEADER_DOMAIN_RFD; - packet[1] = parentAgentList->getOwnerType(); - - while (!domainServerCheckinStopFlag) { - gettimeofday(&lastSend, NULL); - - packSocket(packet + 2, localAddress, htons(parentAgentList->getSocketListenPort())); - - parentAgentList->getAgentSocket()->send(DOMAIN_IP, DOMAINSERVER_PORT, packet, sizeof(packet)); - - packet[0] = PACKET_HEADER_DOMAIN_LIST_REQUEST; - - double usecToSleep = DOMAIN_SERVER_CHECK_IN_USECS - (usecTimestampNow() - usecTimestamp(&lastSend)); - - if (usecToSleep > 0) { - usleep(usecToSleep); - } - } - - pthread_exit(0); - return NULL; -} - -void AgentList::startDomainServerCheckInThread() { - pthread_create(&checkInWithDomainServerThread, NULL, checkInWithDomainServer, (void*) this); -} - -void AgentList::stopDomainServerCheckInThread() { - domainServerCheckinStopFlag = true; - pthread_join(checkInWithDomainServerThread, NULL); -} - AgentList::iterator AgentList::begin() const { Agent** agentBucket = NULL; diff --git a/libraries/shared/src/AgentList.h b/libraries/shared/src/AgentList.h index e5db88569c..2c07b7c34f 100644 --- a/libraries/shared/src/AgentList.h +++ b/libraries/shared/src/AgentList.h @@ -26,6 +26,8 @@ const int MAX_PACKET_SIZE = 1500; const unsigned int AGENT_SOCKET_LISTEN_PORT = 40103; const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000; +const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000; + extern const char SOLO_AGENT_TYPES[3]; extern char DOMAIN_HOSTNAME[]; @@ -46,6 +48,18 @@ public: AgentListIterator begin() const; AgentListIterator end() const; + char getOwnerType() const { return _ownerType; } + + uint16_t getLastAgentID() const { return _lastAgentID; } + void increaseAgentID() { ++_lastAgentID; } + + uint16_t getOwnerID() const { return _ownerID; } + void setOwnerID(uint16_t ownerID) { _ownerID = ownerID; } + + UDPSocket* getAgentSocket() { return &_agentSocket; } + + unsigned int getSocketListenPort() const { return _socketListenPort; }; + void(*linkedDataCreateCallback)(Agent *); int size() { return _numAgents; } @@ -53,6 +67,8 @@ public: void lock() { pthread_mutex_lock(&mutex); } void unlock() { pthread_mutex_unlock(&mutex); } + void setAgentTypesOfInterest(const unsigned char* agentTypesOfInterest, int numAgentTypesOfInterest); + void sendDomainServerCheckIn(); int processDomainServerList(unsigned char *packetData, size_t dataBytes); Agent* agentWithAddress(sockaddr *senderAddress); @@ -67,26 +83,11 @@ public: int updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes); void broadcastToAgents(unsigned char *broadcastData, size_t dataBytes, const char* agentTypes, int numAgentTypes); - unsigned int getSocketListenPort(); - - char getOwnerType() const { return _ownerType; } - - uint16_t getLastAgentID() const { return _lastAgentID; } - void increaseAgentID() { ++_lastAgentID; } - - uint16_t getOwnerID() const { return _ownerID; } - void setOwnerID(uint16_t ownerID) { _ownerID = ownerID; } - - UDPSocket* getAgentSocket() { return &_agentSocket; } - - unsigned int getSocketListenPort() const { return _socketListenPort; }; Agent* soloAgentOfType(char agentType); void startSilentAgentRemovalThread(); void stopSilentAgentRemovalThread(); - void startDomainServerCheckInThread(); - void stopDomainServerCheckInThread(); void startPingUnknownAgentsThread(); void stopPingUnknownAgentsThread(); @@ -105,6 +106,7 @@ private: int _numAgents; UDPSocket _agentSocket; char _ownerType; + unsigned char* _agentTypesOfInterest; unsigned int _socketListenPort; uint16_t _ownerID; uint16_t _lastAgentID; diff --git a/libraries/shared/src/AgentTypes.h b/libraries/shared/src/AgentTypes.h index 8bc97b5ba3..56e900c923 100644 --- a/libraries/shared/src/AgentTypes.h +++ b/libraries/shared/src/AgentTypes.h @@ -16,12 +16,13 @@ // If you don't then it will make things harder on your co-developers in debugging because the Agent // class won't know the name and will report it as "Unknown". -const char AGENT_TYPE_DOMAIN = 'D'; -const char AGENT_TYPE_VOXEL_SERVER = 'V'; -const char AGENT_TYPE_AVATAR = 'I'; -const char AGENT_TYPE_AUDIO_MIXER = 'M'; -const char AGENT_TYPE_AVATAR_MIXER = 'W'; -const char AGENT_TYPE_AUDIO_INJECTOR = 'A'; -const char AGENT_TYPE_ANIMATION_SERVER = 'a'; +typedef char AGENT_TYPE; +const AGENT_TYPE AGENT_TYPE_DOMAIN = 'D'; +const AGENT_TYPE AGENT_TYPE_VOXEL_SERVER = 'V'; +const AGENT_TYPE AGENT_TYPE_AVATAR = 'I'; +const AGENT_TYPE AGENT_TYPE_AUDIO_MIXER = 'M'; +const AGENT_TYPE AGENT_TYPE_AVATAR_MIXER = 'W'; +const AGENT_TYPE AGENT_TYPE_AUDIO_INJECTOR = 'A'; +const AGENT_TYPE AGENT_TYPE_ANIMATION_SERVER = 'a'; #endif