From 9d5a800c6f72474b1ef191c90a81ad87814f74e8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 19 Feb 2013 16:38:57 -0800 Subject: [PATCH] begin abstraction of Agent communication to shared classes --- interface/src/Agent.cpp | 206 ------------------------------------- interface/src/Agent.h | 36 ------- interface/src/main.cpp | 55 +++++----- shared/src/Agent.cpp | 77 ++++++++++++++ shared/src/Agent.h | 33 ++++++ shared/src/AgentData.h | 17 +++ shared/src/AgentList.cpp | 49 +++++++++ shared/src/AgentList.h | 32 ++++++ shared/src/AgentSocket.cpp | 37 +++++++ shared/src/AgentSocket.h | 24 +++++ 10 files changed, 295 insertions(+), 271 deletions(-) delete mode 100644 interface/src/Agent.cpp delete mode 100644 interface/src/Agent.h create mode 100644 shared/src/Agent.cpp create mode 100644 shared/src/Agent.h create mode 100644 shared/src/AgentData.h create mode 100644 shared/src/AgentList.cpp create mode 100644 shared/src/AgentList.h create mode 100644 shared/src/AgentSocket.cpp create mode 100644 shared/src/AgentSocket.h diff --git a/interface/src/Agent.cpp b/interface/src/Agent.cpp deleted file mode 100644 index c062f8d9d4..0000000000 --- a/interface/src/Agent.cpp +++ /dev/null @@ -1,206 +0,0 @@ -// -// Agent.cpp -// interface -// -// Created by Philip Rosedale on 11/20/12. -// Copyright (c) 2012 High Fidelity, Inc. All rights reserved. -// - -#include -#include "Agent.h" -#include "Head.h" -#include "Util.h" - - -// Structure to hold references to other agents that are nearby - -const int MAX_AGENTS = 100; -struct AgentList { - char public_address[255]; - unsigned short public_port; - char private_address[255]; - unsigned short private_port; - char *goodAddress; - unsigned short goodPort; - timeval pingStarted; - int pingMsecs; - char agentType; - bool isSelf; - Head head; -} agents[MAX_AGENTS]; - -int num_agents = 0; - - -char * getAgentAddress(int agentNumber) { - if (agentNumber < getAgentCount()) return agents[agentNumber].public_address; - else return NULL; -} - -int getAgentCount() { - return num_agents; -} - -int getAgentPing(int agentNumber) { - if (agentNumber < getAgentCount()) return agents[agentNumber].pingMsecs; - else return -1; -} - -// -// Process an incoming domainserver packet telling you about other nearby agents, -// and returns the number of agents that were reported. -// -int update_agents(char * data, int length) { - int numAgents = 0; - std::string packet(data, length); - size_t spot; - size_t start_spot = 0; - char *public_address = new char[255]; - char *private_address = new char[255]; - char agentType; - unsigned short public_port, private_port; - spot = packet.find_first_of (",", 0); - while (spot != std::string::npos) { - std::string thisAgent = packet.substr(start_spot, spot-start_spot); - sscanf(thisAgent.c_str(), "%c %s %hd %s %hd", &agentType, public_address, &public_port, private_address, &private_port); - add_agent(public_address, public_port, private_address, private_port, agentType); - numAgents++; - start_spot = spot + 1; - if (start_spot < packet.length()) - spot = packet.find_first_of (",", start_spot); - else spot = std::string::npos; - } - return numAgents; -} - -// Render the heads of the agents -void render_agents(int renderSelf, float * myLocation) { - for (int i = 0; i < num_agents; i++) { - glm::vec3 pos = agents[i].head.getPos(); - glPushMatrix(); - if (!agents[i].isSelf || renderSelf) { - glTranslatef(-pos.x, -pos.y, -pos.z); - agents[i].head.render(0, myLocation); - } - glPopMatrix(); - } -} - -// -// Update a single agent with data received from that agent's IP address -// -void update_agent(char * address, unsigned short port, char * data, int length) -{ - //printf("%s:%d\n", address, port); - for (int i = 0; i < num_agents; i++) { - if ((strcmp(address, agents[i].public_address) == 0) && (agents[i].public_port == port)) { - // Update the agent - agents[i].head.recvBroadcastData(data, length); - if ((strcmp(address, "127.0.0.1") == 0) && (port == AGENT_UDP_PORT)) { - agents[i].isSelf = true; - } else agents[i].isSelf = false; - } - } -} - -// -// Look for an agent by it's IP number, add if it does not exist in local list -// -int add_agent(char * address, unsigned short port, char *private_address, unsigned short private_port, char agentType) { - //std::cout << "Checking for " << IP->c_str() << " "; - for (int i = 0; i < num_agents; i++) { - if ((strcmp(address, agents[i].public_address) == 0) && (agents[i].public_port == port)) { - //std::cout << "Found agent!\n"; - return 0; - } - } - if (num_agents < MAX_AGENTS) { - strcpy(agents[num_agents].public_address, address); - agents[num_agents].public_port = port; - agents[num_agents].agentType = agentType; - strcpy(agents[num_agents].private_address, private_address); - agents[num_agents].private_port = private_port; - agents[num_agents].goodAddress = NULL; - std::cout << "Added Agent # " << num_agents << " with Address " << - agents[num_agents].public_address << ":" << agents[num_agents].public_port << " T: " << - agentType << " (" << agents[num_agents].private_address << ":" << agents[num_agents].private_port << ")\n"; - - num_agents++; - return 1; - } else { - std::cout << "Max agents reached fail!\n"; - return 0; - } -} - -// -// Broadcast data to all the other agents you are aware of, returns 1 if success -// -int broadcastToAgents(UDPSocket *handle, char * data, int length, int sendToSelf) { - int sent_bytes; - //printf("broadcasting to %d agents\n", num_agents); - for (int i = 0; i < num_agents; i++) { - if (agents[i].agentType != 'M' && agents[i].goodAddress != NULL) { -// std::cout << "broadcasting my agent data to: " << agents[i].goodAddress << " : " << agents[i].goodPort << "\n"; - - sent_bytes = handle->send(agents[i].goodAddress, agents[i].goodPort, data, length); - if (sent_bytes != length) { - std::cout << "Broadcast to agents FAILED\n"; - return 0; - } - } - } - return 1; -} - -// Ping other agents to see how fast we are running -void pingAgents(UDPSocket *handle) { - char payload[] = "P"; - for (int i = 0; i < num_agents; i++) { - if (agents[i].agentType != 'M') { - gettimeofday(&agents[i].pingStarted, NULL); - if (agents[i].goodAddress == NULL) { - handle->send(agents[i].public_address, agents[i].public_port, payload, 1); - handle->send(agents[i].private_address, agents[i].private_port, payload, 1); - } else { - handle->send(agents[i].goodAddress, agents[i].goodPort, payload, 1); - } - //printf("\nSent Ping at %d usecs\n", agents[i].pingStarted.tv_usec); - } - - } -} - -// On receiving a ping reply, save that with the agent record -void setAgentPing(char * address, unsigned short port) { - for (int i = 0; i < num_agents; i++) { - bool isLocal = false; - bool isPublic = false; - if ((strcmp(address, agents[i].public_address) == 0) && (agents[i].public_port == port)) { - isPublic = true; - agents[i].goodAddress = agents[i].public_address; - agents[i].goodPort = agents[i].public_port; - } else if ((strcmp(address, agents[i].private_address) == 0) && (agents[i].private_port == port)) { - isLocal = true; - agents[i].goodAddress = agents[i].private_address; - agents[i].goodPort = agents[i].private_port; - } - - if (isPublic || isLocal) { - timeval pingReceived; - gettimeofday(&pingReceived, NULL); - float pingMsecs = diffclock(&agents[i].pingStarted, &pingReceived); - //printf("Received ping at %d usecs, Agent ping = %3.1f\n", pingReceived.tv_usec, pingMsecs); - agents[i].pingMsecs = pingMsecs; - } - } -} - -void kludgyMixerUpdate(Audio audio) { - for (int i = 0; i < num_agents; i++) { - if (agents[i].agentType == 'M') { - audio.updateMixerParams(agents[i].private_address, agents[i].private_port); - } - } -} - diff --git a/interface/src/Agent.h b/interface/src/Agent.h deleted file mode 100644 index 460491fde7..0000000000 --- a/interface/src/Agent.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Agent.h -// interface -// -// Created by Philip Rosedale on 11/20/12. -// Copyright (c) 2012 High Fidelity, Inc. All rights reserved. -// - -#ifndef __interface__Agent__ -#define __interface__Agent__ - -#include -#include -#include -#include -#include -#include -#include -#include "UDPSocket.h" -#include "Audio.h" - -const unsigned short AGENT_UDP_PORT = 40103; - -int update_agents(char * data, int length); -int add_agent(char * address, unsigned short port, char *private_address, unsigned short private_port, char agentType); -int broadcastToAgents(UDPSocket * handle, char * data, int length, int sendToSelf); -void pingAgents(UDPSocket *handle); -void setAgentPing(char * address, unsigned short port); -void update_agent(char * address, unsigned short port, char * data, int length); -void render_agents(int renderSelf, float * myLocation); -void kludgyMixerUpdate(Audio audio); -int getAgentPing(int agentNumber); -int getAgentCount(); -char * getAgentAddress(int agentNumber); - -#endif diff --git a/interface/src/main.cpp b/interface/src/main.cpp index f799926aad..d98292176c 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -25,13 +25,8 @@ #include #include #include - -// These includes are for the serial port reading/writing -#include -#include -#include #include - +#include #include "SerialInterface.h" #include "Field.h" #include "world.h" @@ -42,7 +37,7 @@ #include "Particle.h" #include "Texture.h" #include "Cloud.h" -#include "Agent.h" +#include "AgentList.h" #include "Cube.h" #include "Lattice.h" #include "Finger.h" @@ -62,7 +57,8 @@ 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 const int DOMAINSERVER_PORT = 40102; -UDPSocket agentSocket(AGENT_UDP_PORT); +UDPSocket agentSocket(AGENT_SOCKET_LISTEN_PORT); +AgentList agentList; // For testing, add milliseconds of delay for received UDP packets char* incomingPacket; @@ -227,13 +223,13 @@ 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_UDP_PORT); + 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); agentSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, output, packet_size); // Ping the agents we can see - pingAgents(&agentSocket); +// pingAgents(&agentSocket); if (0) { // Massive send packet speed test @@ -243,7 +239,7 @@ void Timer(int extra) junk[0] = 'J'; for (int i = 0; i < 10000; i++) { - agentSocket.send((char *)"192.168.1.38", AGENT_UDP_PORT, junk, 1000); +// agentSocket.send((char *)"192.168.1.38", AGENT_UDP_PORT, junk, 1000); } gettimeofday(&endtest, NULL); float sendTime = diffclock(&starttest, &endtest); @@ -273,12 +269,12 @@ void display_stats(void) } // Output the ping times to the various agents - std::stringstream pingTimes; - pingTimes << "Agent Pings, msecs:"; - for (int i = 0; i < getAgentCount(); i++) { - pingTimes << " " << getAgentAddress(i) << ": " << getAgentPing(i); - } - drawtext(10,50,0.10, 0, 1.0, 0, (char *)pingTimes.str().c_str()); +// std::stringstream pingTimes; +// pingTimes << "Agent Pings, msecs:"; +// for (int i = 0; i < getAgentCount(); i++) { +// pingTimes << " " << getAgentAddress(i) << ": " << getAgentPing(i); +// } +// drawtext(10,50,0.10, 0, 1.0, 0, (char *)pingTimes.str().c_str()); std::stringstream angles; @@ -518,7 +514,7 @@ void update_pos(float frametime) const int MAX_BROADCAST_STRING = 200; char broadcast_string[MAX_BROADCAST_STRING]; int broadcast_bytes = myHead.getBroadcastData(broadcast_string); - broadcastToAgents(&agentSocket, broadcast_string, broadcast_bytes, sendToSelf); +// broadcastToAgents(&agentSocket, broadcast_string, broadcast_bytes, sendToSelf); } int render_test_spot = WIDTH/2; @@ -567,8 +563,8 @@ void display(void) if (display_field) field.render(); // Render heads of other agents - render_agents(sendToSelf, &location[0]); - +// render_agents(sendToSelf, &location[0]); + if (display_hand) myHand.render(); if (!display_head) balls.render(); @@ -780,12 +776,12 @@ void *networkReceive(void *args) // //printf("Replying to ping!\n"); char reply[] = "R"; - agentSocket.send(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port), reply, 1); +// agentSocket.send(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port), reply, 1); } else if (incomingPacket[0] == 'R') { // // Got Reply, record as appropriate // - setAgentPing(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port)); +// setAgentPing(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port)); } else if (incomingPacket[0] == 'M') { // @@ -799,19 +795,20 @@ void *networkReceive(void *args) // Message from domainserver // //printf("agent list received!\n"); - nearbyAgents = update_agents(&incomingPacket[1], bytesReceived - 1); - kludgyMixerUpdate(audio); + nearbyAgents = agentList.updateList(&incomingPacket[1]); + std::cout << "Received " << nearbyAgents << " from DS!\n"; +// kludgyMixerUpdate(audio); } else if (incomingPacket[0] == 'H') { // // Broadcast packet from another agent // //printf("broadcast received"); - update_agent(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port), &incomingPacket[1], bytesReceived - 1); +// update_agent(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port), &incomingPacket[1], bytesReceived - 1); } else if (incomingPacket[0] == 'T') { // Received a self-test packet (to get one's own IP), copy it to local variable! - printf("My Address: %s:%u\n", - inet_ntoa(senderAddress.sin_addr), - senderAddress.sin_port); +// printf("My Address: %s:%u\n", +// inet_ntoa(senderAddress.sin_addr), +// senderAddress.sin_port); } } } @@ -939,7 +936,7 @@ int main(int argc, char** argv) 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); +// inet_ntop(AF_INET, tmpAddrPtr, localAddressBuffer, INET_ADDRSTRLEN); } } diff --git a/shared/src/Agent.cpp b/shared/src/Agent.cpp new file mode 100644 index 0000000000..229db3150f --- /dev/null +++ b/shared/src/Agent.cpp @@ -0,0 +1,77 @@ +// +// Agent.cpp +// hifi +// +// Created by Stephen Birarda on 2/15/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include "Agent.h" + +Agent::Agent() { + +} + +Agent::Agent(AgentSocket *agentPublicSocket, AgentSocket *agentLocalSocket, char agentType) { + publicSocket = new AgentSocket(*agentPublicSocket); + localSocket = new AgentSocket(*agentLocalSocket); + activeSocket = NULL; + type = agentType; + + linkedData = 0; +} + +Agent::Agent(const Agent &otherAgent) { + publicSocket = new AgentSocket(*otherAgent.publicSocket); + localSocket = new AgentSocket(*otherAgent.localSocket); + + if (otherAgent.activeSocket == otherAgent.publicSocket) { + activeSocket = publicSocket; + } else if (otherAgent.activeSocket == otherAgent.localSocket) { + activeSocket = localSocket; + } else { + activeSocket = NULL; + } + + type = otherAgent.type; + + // copy over linkedData +} + +Agent& Agent::operator=(const Agent &otherAgent) { + if (this != &otherAgent) { + // deallocate old memory + delete publicSocket; + delete localSocket; + delete linkedData; + + publicSocket = new AgentSocket(*otherAgent.publicSocket); + localSocket = new AgentSocket(*otherAgent.localSocket); + + if (otherAgent.activeSocket == otherAgent.publicSocket) { + activeSocket = publicSocket; + } else if (otherAgent.activeSocket == otherAgent.localSocket) { + activeSocket = localSocket; + } else { + activeSocket = NULL; + } + + type = otherAgent.type; + } + + return *this; +} + +Agent::~Agent() { + delete publicSocket; + delete localSocket; + delete linkedData; +} + +bool Agent::matches(AgentSocket *otherPublicSocket, AgentSocket *otherLocalSocket, char otherAgentType) { + return publicSocket->port == otherPublicSocket->port + && localSocket->port == otherLocalSocket->port + && type == otherAgentType + && strcmp(publicSocket->address, otherPublicSocket->address) == 0 + && strcmp(localSocket->address, otherLocalSocket->address) == 0; +} \ No newline at end of file diff --git a/shared/src/Agent.h b/shared/src/Agent.h new file mode 100644 index 0000000000..ba6abf14b3 --- /dev/null +++ b/shared/src/Agent.h @@ -0,0 +1,33 @@ +// +// Agent.h +// hifi +// +// Created by Stephen Birarda on 2/15/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __hifi__Agent__ +#define __hifi__Agent__ + +#include +#include "AgentSocket.h" +#include "AgentData.h" + +class Agent { + public: + Agent(); + Agent(AgentSocket *agentPublicSocket, AgentSocket *agentLocalSocket, char agentType); + Agent(const Agent &otherAgent); + Agent& operator=(const Agent &otherAgent); + ~Agent(); + + bool matches(AgentSocket *otherPublicSocket, AgentSocket *otherLocalSocket, char otherAgentType); + AgentSocket *publicSocket, *localSocket, *activeSocket; + char type; + timeval pingStarted; + int pingMsecs; + bool isSelf; + AgentData *linkedData; +}; + +#endif /* defined(__hifi__Agent__) */ diff --git a/shared/src/AgentData.h b/shared/src/AgentData.h new file mode 100644 index 0000000000..667588fed1 --- /dev/null +++ b/shared/src/AgentData.h @@ -0,0 +1,17 @@ +// +// AgentData.h +// hifi +// +// Created by Stephen Birarda on 2/19/13. +// +// + +#ifndef hifi_AgentData_h +#define hifi_AgentData_h + +class AgentData { + public: + virtual ~AgentData(); +}; + +#endif diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp new file mode 100644 index 0000000000..a83da3e438 --- /dev/null +++ b/shared/src/AgentList.cpp @@ -0,0 +1,49 @@ +// +// AgentList.cpp +// hifi +// +// Created by Stephen Birarda on 2/15/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include "AgentList.h" + +int AgentList::updateList(char *packetData) { + int readAgents = 0; + int scannedItems = 0; + + char agentType; + AgentSocket agentPublicSocket = AgentSocket(); + AgentSocket agentLocalSocket = AgentSocket(); + Agent newAgent; + + while((scannedItems = sscanf(packetData, + "%c %s %hd %s %hd,", + &agentType, + agentPublicSocket.address, + &agentPublicSocket.port, + agentLocalSocket.address, + &agentLocalSocket.port + ))) { + std::vector::iterator it; + + for(it = agents.begin(); it != agents.end(); ++it) { + if (it->matches(&agentPublicSocket, &agentLocalSocket, agentType)) { + // we already have this agent, stop checking + break; + } + } + + if (it == agents.end()) { + // we didn't have this agent, so add them + newAgent = Agent(&agentPublicSocket, &agentLocalSocket, agentType); + agents.push_back(newAgent); + } else { + // we had this agent already, don't do anything + } + + readAgents++; + } + + return readAgents; +} \ No newline at end of file diff --git a/shared/src/AgentList.h b/shared/src/AgentList.h new file mode 100644 index 0000000000..72b15ec9fe --- /dev/null +++ b/shared/src/AgentList.h @@ -0,0 +1,32 @@ +// +// AgentList.h +// hifi +// +// Created by Stephen Birarda on 2/15/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __hifi__AgentList__ +#define __hifi__AgentList__ + +#include +#include +#include "Agent.h" + +const unsigned short AGENT_SOCKET_LISTEN_PORT = 40103; + +class AgentList { + public: + std::vector agents; + int updateList(char *packetData); + + int processAgentData(char *address, unsigned short port, char *packetData, size_t dataBytes); + int broadcastToAgents(char *broadcastData, size_t dataBytes, bool sendToSelf); + void pingAgents(); + private: + int addAgent(AgentSocket *publicSocket, AgentSocket *localSocket, char agentType); + int indexOfMatchingAgent(AgentSocket *publicSocket, AgentSocket *privateSocket, char agentType); + +}; + +#endif /* defined(__hifi__AgentList__) */ diff --git a/shared/src/AgentSocket.cpp b/shared/src/AgentSocket.cpp new file mode 100644 index 0000000000..e25f39b31a --- /dev/null +++ b/shared/src/AgentSocket.cpp @@ -0,0 +1,37 @@ +// +// AgentSocket.cpp +// hifi +// +// Created by Stephen Birarda on 2/19/13. +// +// + +#include "AgentSocket.h" + +#define MAX_ADDRESS_SIZE 255 + +AgentSocket::AgentSocket() { + address = new char[MAX_ADDRESS_SIZE]; +} + +AgentSocket::AgentSocket(const AgentSocket &otherAgentSocket) { + address = new char[MAX_ADDRESS_SIZE]; + strcpy(address, otherAgentSocket.address); + port = otherAgentSocket.port; +} + +AgentSocket& AgentSocket::operator=(const AgentSocket &otherAgentSocket) { + + if (this != &otherAgentSocket) { + delete address; + address = new char[MAX_ADDRESS_SIZE]; + strcpy(address, otherAgentSocket.address); + port = otherAgentSocket.port; + } + + return *this; +} + +AgentSocket::~AgentSocket() { + delete address; +} \ No newline at end of file diff --git a/shared/src/AgentSocket.h b/shared/src/AgentSocket.h new file mode 100644 index 0000000000..bd24422635 --- /dev/null +++ b/shared/src/AgentSocket.h @@ -0,0 +1,24 @@ +// +// AgentSocket.h +// hifi +// +// Created by Stephen Birarda on 2/19/13. +// +// + +#ifndef __hifi__AgentSocket__ +#define __hifi__AgentSocket__ + +#include + +class AgentSocket { + public: + AgentSocket(); + AgentSocket(const AgentSocket &otherAgentSocket); + AgentSocket& operator=(const AgentSocket &otherAgentSocket); + ~AgentSocket(); + char *address; + unsigned short port; +}; + +#endif /* defined(__hifi__AgentSocket__) */