From c57380012e2e842dc1fe6bba400c3e6adf65749a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Feb 2013 18:32:23 -0800 Subject: [PATCH] hook domain server up to AgentList, pack sockets --- domain/src/main.cpp | 166 +++++++-------------------------------- interface/src/main.cpp | 27 +++---- shared/src/Agent.cpp | 10 +++ shared/src/Agent.h | 7 +- shared/src/AgentList.cpp | 83 +++++++++++--------- shared/src/AgentList.h | 13 +-- shared/src/UDPSocket.cpp | 23 ++++++ shared/src/UDPSocket.h | 3 + 8 files changed, 133 insertions(+), 199 deletions(-) diff --git a/domain/src/main.cpp b/domain/src/main.cpp index 75eebbb9af..85412a5ec3 100644 --- a/domain/src/main.cpp +++ b/domain/src/main.cpp @@ -27,167 +27,55 @@ #include #include #include -#include "UDPSocket.h" - +#include "AgentList.h" const int DOMAIN_LISTEN_PORT = 40102; -const char DESTINATION_IP[] = "127.0.0.1"; const int MAX_PACKET_SIZE = 1500; -char packet_data[MAX_PACKET_SIZE]; +unsigned char packetData[MAX_PACKET_SIZE]; -const int MAX_AGENTS = 1000; const int LOGOFF_CHECK_INTERVAL = 5000; -struct AgentList { - char agentType; - uint32_t ip; - in_addr public_sin_addr; - unsigned short public_port; - char *private_addr; - unsigned short private_port; - float x, y, z; - bool active; - timeval time, connectTime; -} agents[MAX_AGENTS]; - -int num_agents = 0; int lastActiveCount = 0; +AgentList agentList(DOMAIN_LISTEN_PORT); -UDPSocket domainSocket = UDPSocket(DOMAIN_LISTEN_PORT); - -double diffclock(timeval clock1,timeval clock2) -{ - double diffms = (clock2.tv_sec - clock1.tv_sec) * 1000.0; - diffms += (clock2.tv_usec - clock1.tv_usec) / 1000.0; // us to ms - return diffms; -} - -int addAgent(uint32_t ip, in_port_t port, char *private_ip, unsigned short private_port, char agentType, float x, float y, float z) { - // Search for agent in list and add if needed - int i = 0; - int is_new = 0; - while ((ip != agents[i].ip || port != agents[i].public_port) && (i < num_agents)) { - i++; - } +int listForBroadcast(unsigned char *listBuffer) { + unsigned char *currentBufferPos = listBuffer + 1; + unsigned char *startPointer = currentBufferPos; - if ((i == num_agents) || (agents[i].active == false)) { - is_new = 1; - agents[i].private_addr = new char[255]; - } - - agents[i].ip = ip; - agents[i].x = x; - agents[i].y = y; - agents[i].z = z; - agents[i].active = true; - agents[i].public_sin_addr.s_addr = ip; - agents[i].public_port = port; - strcpy(agents[i].private_addr, private_ip); - agents[i].private_port = private_port; - agents[i].agentType = agentType; - gettimeofday(&agents[i].time, NULL); - if (is_new) gettimeofday(&agents[i].connectTime, NULL); - if (i == num_agents) { - num_agents++; - } - return is_new; -} - -void update_agent_list(timeval now) { - int i; - //std::cout << "Checking agent list" << "\n"; - for (i = 0; i < num_agents; i++) { - if ((diffclock(agents[i].time, now) > LOGOFF_CHECK_INTERVAL) && - agents[i].active) { - std::cout << "Expired Agent type " << agents[i].agentType << " from " << - inet_ntoa(agents[i].public_sin_addr) << ":" << agents[i].public_port << "\n"; - agents[i].active = false; - } - } -} - -void send_agent_list(sockaddr_in *agentAddrPointer) { - int i, length = 0; - ssize_t sentBytes; - char buffer[MAX_PACKET_SIZE]; - char * public_address; - char public_portstring[10]; - char * private_address; - char private_portstring[10]; - int numSent = 0; - buffer[length++] = 'D'; - //std::cout << "send list to: " << inet_ntoa(dest_address->sin_addr) << "\n"; - for (i = 0; i < num_agents; i++) { - if (agents[i].active) { - // Write the type of the agent - buffer[length++] = agents[i].agentType; - // Write agent's public IP address - public_address = inet_ntoa(agents[i].public_sin_addr); - memcpy(&buffer[length], public_address, strlen(public_address)); - length += strlen(public_address); - // Add public port number - buffer[length++] = ' '; - sprintf(public_portstring, "%hd", agents[i].public_port); - memcpy(&buffer[length], public_portstring, strlen(public_portstring)); - length += strlen(public_portstring); - // Write agent's private IP address - buffer[length++] = ' '; - private_address = agents[i].private_addr; - memcpy(&buffer[length], private_address, strlen(private_address)); - length += strlen(private_address); - // Add private port number - buffer[length++] = ' '; - sprintf(private_portstring, "%hd,", agents[i].private_port); - memcpy(&buffer[length], private_portstring, strlen(private_portstring)); - length += strlen(private_portstring); - numSent++; - } - } - - std::cout << "The sent buffer was " << buffer << "\n"; - - if (length > 1) { - sentBytes = domainSocket.send(agentAddrPointer, buffer, length); + for(std::vector::iterator agent = agentList.agents.begin(); agent != agentList.agents.end(); agent++) { + *currentBufferPos++ = agent->type; - if (sentBytes < length) - std::cout << "Error sending agent list!\n"; - else if (numSent != lastActiveCount) { - std::cout << numSent << " Active Agents\n"; - lastActiveCount = numSent; - } + currentBufferPos += packSocket(currentBufferPos, agent->publicSocket); + currentBufferPos += packSocket(currentBufferPos, agent->localSocket); } + return 1 + (currentBufferPos - startPointer); // 1 is added for the leading 'D' } int main(int argc, const char * argv[]) { ssize_t receivedBytes = 0; - timeval time, last_time; - sockaddr_in agentAddress; + char agentType; + unsigned char *broadcastPacket = new unsigned char[MAX_PACKET_SIZE]; + *broadcastPacket = 'D'; - gettimeofday(&last_time, NULL); + sockaddr_in agentPublicAddress, agentLocalAddress; + agentLocalAddress.sin_family = AF_INET; + while (true) { - if (domainSocket.receive(&agentAddress, packet_data, &receivedBytes)) { - float x,y,z; - char agentType; - char private_ip[50]; - unsigned short private_port; - sscanf(packet_data, "%c %f,%f,%f,%s %hd", &agentType, &x, &y, &z, private_ip, &private_port); - if (addAgent(agentAddress.sin_addr.s_addr, ntohs(agentAddress.sin_port), private_ip, private_port, agentType, x, y, z)) { - std::cout << "Added Agent, type " << agentType << " from " << - inet_ntoa(agentAddress.sin_addr) << ":" << ntohs(agentAddress.sin_port) << - " (" << private_ip << ":" << private_port << ")" << "\n"; + if (agentList.getAgentSocket()->receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) { + agentType = packetData[0]; + unpackSocket(&packetData[1], (sockaddr *)&agentLocalAddress); + + agentList.addOrUpdateAgent((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType); + + int listBytes = listForBroadcast(broadcastPacket); + + if (listBytes > 0) { + agentList.getAgentSocket()->send((sockaddr *)&agentPublicAddress, broadcastPacket, listBytes); } - // Reply with packet listing nearby active agents - send_agent_list(&agentAddress); - } - - gettimeofday(&time, NULL); - if (diffclock(last_time, time) > LOGOFF_CHECK_INTERVAL) { - gettimeofday(&last_time, NULL); - update_agent_list(last_time); } } return 0; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 01d0696ad9..60f828f8a5 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -55,14 +55,12 @@ int simulate_on = 1; const int MAX_PACKET_SIZE = 1500; char DOMAIN_HOSTNAME[] = "highfidelity.below92.com"; -char DOMAIN_IP[100] = ""; // IP Address will be used first if not empty string +char DOMAIN_IP[100] = "192.168.1.47"; // IP Address will be used first if not empty string const int DOMAINSERVER_PORT = 40102; AgentList agentList; // For testing, add milliseconds of delay for received UDP packets -char* incomingPacket; - int packetcount = 0; int packets_per_second = 0; int bytes_per_second = 0; @@ -79,7 +77,7 @@ int WIDTH = 1200; int HEIGHT = 800; int fullscreen = 0; -char localAddressBuffer[INET_ADDRSTRLEN]; +in_addr_t localAddress; Oscilloscope audioScope(512,200,true); @@ -222,11 +220,11 @@ void Timer(int extra) // // Send a message to the domainserver telling it we are ALIVE // - char output[100]; - sprintf(output, "%c %f,%f,%f,%s %hd", 'I', location[0], location[1], location[2], localAddressBuffer, AGENT_SOCKET_LISTEN_PORT); - std::cout << "sending " << output << " to domain server\n"; - int packet_size = strlen(output); - agentList.getAgentSocket()->send(DOMAIN_IP, DOMAINSERVER_PORT, output, packet_size); + unsigned char output[7]; + output[0] = 'I'; + packSocket(output + 1, localAddress, htons(AGENT_SOCKET_LISTEN_PORT)); + + agentList.getAgentSocket()->send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7); // Ping the agents we can see agentList.pingAgents(); @@ -764,8 +762,10 @@ void *networkReceive(void *args) { sockaddr senderAddress; ssize_t bytesReceived; + unsigned char *incomingPacket = new unsigned char[MAX_PACKET_SIZE]; + while (true) { - if (agentList.getAgentSocket()->receive(&senderAddress, (void *)incomingPacket, &bytesReceived)) { + if (agentList.getAgentSocket()->receive(&senderAddress, incomingPacket, &bytesReceived)) { packetcount++; bytescount += bytesReceived; @@ -926,20 +926,15 @@ void *poll_marker_capture(void *threadarg){ int main(int argc, char** argv) { - // Create network socket and buffer - incomingPacket = new char[MAX_PACKET_SIZE]; - struct ifaddrs * ifAddrStruct=NULL; struct ifaddrs * ifa=NULL; - void * tmpAddrPtr=NULL; getifaddrs(&ifAddrStruct); for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4 // is a valid IP4 Address - tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; -// inet_ntop(AF_INET, tmpAddrPtr, localAddressBuffer, INET_ADDRSTRLEN); + localAddress = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; } } diff --git a/shared/src/Agent.cpp b/shared/src/Agent.cpp index e25d4c4763..7db0fb96fa 100644 --- a/shared/src/Agent.cpp +++ b/shared/src/Agent.cpp @@ -77,4 +77,14 @@ bool Agent::matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, cha return type == otherAgentType && socketMatch(publicSocket, otherPublicSocket) && socketMatch(localSocket, otherLocalSocket); +} + +std::ostream& operator<<(std::ostream& os, const Agent* agent) { + sockaddr_in *agentPublicSocket = (sockaddr_in *)agent->publicSocket; + sockaddr_in *agentLocalSocket = (sockaddr_in *)agent->localSocket; + + os << "T: " << agent->type << " PA: " << inet_ntoa(agentPublicSocket->sin_addr) << + ":" << ntohs(agentPublicSocket->sin_port) << " LA: " << inet_ntoa(agentLocalSocket->sin_addr) << + ":" << ntohs(agentLocalSocket->sin_port); + return os; } \ No newline at end of file diff --git a/shared/src/Agent.h b/shared/src/Agent.h index 7f0b4da2cf..59ec0e612c 100644 --- a/shared/src/Agent.h +++ b/shared/src/Agent.h @@ -21,16 +21,21 @@ class Agent { Agent& operator=(Agent otherAgent); bool operator==(const Agent& otherAgent); ~Agent(); - + bool matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, char otherAgentType); + sockaddr *publicSocket, *localSocket, *activeSocket; char type; timeval pingStarted; int pingMsecs; bool isSelf; AgentData *linkedData; + + friend std::ostream& operator<<(std::ostream& os, const Agent* agent); private: void swap(Agent &first, Agent &second); }; +std::ostream& operator<<(std::ostream& os, const Agent* agent); + #endif /* defined(__hifi__Agent__) */ diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index f10d08fe27..9b1d63e51b 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -7,21 +7,26 @@ // #include "AgentList.h" +#include AgentList::AgentList() : agentSocket(AGENT_SOCKET_LISTEN_PORT) { } +AgentList::AgentList(int socketListenPort) : agentSocket(socketListenPort) { + +} + UDPSocket * AgentList::getAgentSocket() { return &agentSocket; } -void AgentList::processAgentData(sockaddr *senderAddress, char *packetData, size_t dataBytes) { +void AgentList::processAgentData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) { switch (packetData[0]) { case 'D': { // list of agents from domain server - updateList(packetData); + updateList(packetData, dataBytes); break; } case 'P': @@ -40,52 +45,54 @@ void AgentList::processAgentData(sockaddr *senderAddress, char *packetData, size } } -int AgentList::updateList(char *packetData) { +int AgentList::updateList(unsigned char *packetData, size_t dataBytes) { int readAgents = 0; - int scannedItems = 0; - + char agentType; // assumes only IPv4 addresses - sockaddr_in *agentPublicSocket = new sockaddr_in; - agentPublicSocket->sin_family = AF_INET; - sockaddr_in *agentLocalSocket = new sockaddr_in; - agentLocalSocket->sin_family = AF_INET; + sockaddr_in agentPublicSocket; + agentPublicSocket.sin_family = AF_INET; + sockaddr_in agentLocalSocket; + agentLocalSocket.sin_family = AF_INET; + unsigned char *readPtr = packetData + 1; + unsigned char *startPtr = packetData; - Agent newAgent; - - while((scannedItems = sscanf(packetData, - "%c %u %hd %u %hd,", - &agentType, - &agentPublicSocket->sin_addr.s_addr, - &agentPublicSocket->sin_port, - &agentLocalSocket->sin_addr.s_addr, - &agentLocalSocket->sin_port - ))) { + while((readPtr - startPtr) < dataBytes) { + agentType = *readPtr++; + readPtr += unpackSocket(readPtr, (sockaddr *)&agentPublicSocket); + readPtr += unpackSocket(readPtr, (sockaddr *)&agentLocalSocket); - std::vector::iterator agent; - - for(agent = agents.begin(); agent != agents.end(); agent++) { - if (agent->matches((sockaddr *)&agentPublicSocket, (sockaddr *)&agentLocalSocket, agentType)) { - // we already have this agent, stop checking - break; - } + addOrUpdateAgent((sockaddr *)&agentPublicSocket, (sockaddr *)&agentLocalSocket, agentType); + } + + return readAgents; +} + +bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType) { + std::vector::iterator agent; + + for(agent = agents.begin(); agent != agents.end(); agent++) { + if (agent->matches(publicSocket, localSocket, agentType)) { + // we already have this agent, stop checking + break; } - - if (agent == agents.end()) { - // we didn't have this agent, so add them - newAgent = Agent((sockaddr *)agentPublicSocket, (sockaddr *)agentLocalSocket, agentType); - std::cout << "Added new agent - PS: " << agentPublicSocket << " LS: " << agentLocalSocket << " AT: " << agentType << "\n"; - agents.push_back(newAgent); - } else { - // we had this agent already, don't do anything - } - - readAgents++; } - return readAgents; + if (agent == agents.end()) { + // we didn't have this agent, so add them + Agent newAgent = Agent(publicSocket, localSocket, agentType); + + std::cout << "Added agent - " << &newAgent << "\n"; + + agents.push_back(newAgent); + + return true; + } else { + // we had this agent already + return false; + } } void AgentList::pingAgents() { diff --git a/shared/src/AgentList.h b/shared/src/AgentList.h index b1be10324c..6f34c7b3b9 100644 --- a/shared/src/AgentList.h +++ b/shared/src/AgentList.h @@ -19,16 +19,19 @@ const unsigned short AGENT_SOCKET_LISTEN_PORT = 40103; class AgentList { public: AgentList(); + AgentList(int socketListenPort); std::vector agents; - int updateList(char *packetData); - void processAgentData(sockaddr *senderAddress, char *packetData, size_t dataBytes); - int broadcastToAgents(char *broadcastData, size_t dataBytes, bool sendToSelf); - void pingAgents(); UDPSocket* getAgentSocket(); + + int updateList(unsigned char *packetData, size_t dataBytes); + bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType); + void processAgentData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes); + void broadcastToAgents(char *broadcastData, size_t dataBytes, bool sendToSelf); + void pingAgents(); private: UDPSocket agentSocket; - int addAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType); + void handlePingReply(sockaddr *agentAddress); }; diff --git a/shared/src/UDPSocket.cpp b/shared/src/UDPSocket.cpp index 1cac63a985..fd6102f367 100644 --- a/shared/src/UDPSocket.cpp +++ b/shared/src/UDPSocket.cpp @@ -36,6 +36,29 @@ bool socketMatch(sockaddr *first, sockaddr *second) { } } +int packSocket(unsigned char *packStore, in_addr_t inAddress, in_port_t networkOrderPort) { + packStore[0] = inAddress >> 24; + packStore[1] = inAddress >> 16; + packStore[2] = inAddress >> 8; + packStore[3] = inAddress; + + packStore[4] = networkOrderPort >> 8; + packStore[5] = networkOrderPort; + + return 6; // could be dynamically more if we need IPv6 +} + +int packSocket(unsigned char *packStore, sockaddr *socketToPack) { + return packSocket(packStore, ((sockaddr_in *) socketToPack)->sin_addr.s_addr, ((sockaddr_in *) socketToPack)->sin_port); +} + +int unpackSocket(unsigned char *packedData, sockaddr *unpackDestSocket) { + sockaddr_in *destinationSocket = (sockaddr_in *) unpackDestSocket; + destinationSocket->sin_addr.s_addr = (packedData[0] << 24) + (packedData[1] << 16) + (packedData[2] << 8) + packedData[3]; + destinationSocket->sin_port = (packedData[4] << 8) + packedData[5]; + return 6; // this could be more if we ever need IPv6 +} + UDPSocket::UDPSocket(int listeningPort) { // create the socket handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); diff --git a/shared/src/UDPSocket.h b/shared/src/UDPSocket.h index 47ff8ffaee..27a3c48ad3 100644 --- a/shared/src/UDPSocket.h +++ b/shared/src/UDPSocket.h @@ -28,5 +28,8 @@ class UDPSocket { }; bool socketMatch(sockaddr *first, sockaddr *second); +int packSocket(unsigned char *packStore, in_addr_t inAddress, in_port_t networkOrderPort); +int packSocket(unsigned char *packStore, sockaddr *socketToPack); +int unpackSocket(unsigned char *packedData, sockaddr *unpackDestSocket); #endif /* defined(__interface__UDPSocket__) */