From 720581747675e78bf41d6f4e1eac9da726c102d3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Feb 2013 11:44:35 -0800 Subject: [PATCH] remove AgentSocket abstraction to use sockaddr struct --- interface/src/main.cpp | 89 ++++++++++++++++++++------------------ shared/src/Agent.cpp | 37 +++++++++++----- shared/src/Agent.h | 9 ++-- shared/src/AgentList.cpp | 70 +++++++++++++++++++++++++----- shared/src/AgentList.h | 9 ++-- shared/src/AgentSocket.cpp | 38 ---------------- shared/src/AgentSocket.h | 32 -------------- shared/src/UDPSocket.cpp | 37 +++++++++++----- shared/src/UDPSocket.h | 8 ++-- 9 files changed, 169 insertions(+), 160 deletions(-) delete mode 100644 shared/src/AgentSocket.cpp delete mode 100644 shared/src/AgentSocket.h diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 2af6319bf6..01d0696ad9 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -762,54 +762,57 @@ void key(unsigned char k, int x, int y) // void *networkReceive(void *args) { - sockaddr_in senderAddress; + sockaddr senderAddress; ssize_t bytesReceived; while (true) { if (agentList.getAgentSocket()->receive(&senderAddress, (void *)incomingPacket, &bytesReceived)) { - packetcount++; bytescount += bytesReceived; - // If packet is a Mouse data packet, copy it over - if (incomingPacket[0] == 'P') { - // - // Got Ping, reply immediately! - // - //printf("Replying to ping!\n"); - char reply[] = "R"; -// 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)); - - } else if (incomingPacket[0] == 'M') { - // - // mouse location packet - // - sscanf(incomingPacket, "M %d %d", &target_x, &target_y); - target_display = 1; - //printf("X = %d Y = %d\n", target_x, target_y); - } else if (incomingPacket[0] == 'D') { - // - // Message from domainserver - // - //printf("agent list received!\n"); - 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); - } 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); - } + + agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived); + + +// // If packet is a Mouse data packet, copy it over +// if (incomingPacket[0] == 'P') { +// // +// // Got Ping, reply immediately! +// // +// //printf("Replying to ping!\n"); +// char reply[] = "R"; +// agentList.getAgentSocket()->send(&senderAddress, reply, 1); +// } else if (incomingPacket[0] == 'R') { +// // +// // Got Reply, record as appropriate +// // +//// setAgentPing(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port)); +// +// } else if (incomingPacket[0] == 'M') { +// // +// // mouse location packet +// // +// sscanf(incomingPacket, "M %d %d", &target_x, &target_y); +// target_display = 1; +// //printf("X = %d Y = %d\n", target_x, target_y); +// } else if (incomingPacket[0] == 'D') { +// // +// // Message from domainserver +// // +// //printf("agent list received!\n"); +// 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); +// } 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); +// } } } diff --git a/shared/src/Agent.cpp b/shared/src/Agent.cpp index 99f8eb9724..e25d4c4763 100644 --- a/shared/src/Agent.cpp +++ b/shared/src/Agent.cpp @@ -7,23 +7,32 @@ // #include "Agent.h" +#include +#include "UDPSocket.h" Agent::Agent() { } -Agent::Agent(AgentSocket *agentPublicSocket, AgentSocket *agentLocalSocket, char agentType) { - publicSocket = new AgentSocket(*agentPublicSocket); - localSocket = new AgentSocket(*agentLocalSocket); - activeSocket = NULL; +Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agentType) { + publicSocket = new sockaddr; + memcpy(publicSocket, agentPublicSocket, sizeof(sockaddr)); + + localSocket = new sockaddr; + memcpy(localSocket, agentLocalSocket, sizeof(sockaddr)); + type = agentType; + activeSocket = NULL; linkedData = NULL; } Agent::Agent(const Agent &otherAgent) { - publicSocket = new AgentSocket(*otherAgent.publicSocket); - localSocket = new AgentSocket(*otherAgent.localSocket); + publicSocket = new sockaddr; + memcpy(publicSocket, otherAgent.publicSocket, sizeof(sockaddr)); + + localSocket = new sockaddr; + memcpy(localSocket, otherAgent.localSocket, sizeof(sockaddr)); if (otherAgent.activeSocket == otherAgent.publicSocket) { activeSocket = publicSocket; @@ -36,6 +45,7 @@ Agent::Agent(const Agent &otherAgent) { type = otherAgent.type; // copy over linkedData + linkedData = NULL; } Agent& Agent::operator=(Agent otherAgent) { @@ -43,6 +53,10 @@ Agent& Agent::operator=(Agent otherAgent) { return *this; } +bool Agent::operator==(const Agent& otherAgent) { + return matches(otherAgent.publicSocket, otherAgent.localSocket, otherAgent.type); +} + void Agent::swap(Agent &first, Agent &second) { using std::swap; swap(first.publicSocket, second.publicSocket); @@ -58,10 +72,9 @@ Agent::~Agent() { 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; +bool Agent::matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, char otherAgentType) { + // checks if two agent objects are the same agent (same type + local + public address) + return type == otherAgentType + && socketMatch(publicSocket, otherPublicSocket) + && socketMatch(localSocket, otherLocalSocket); } \ No newline at end of file diff --git a/shared/src/Agent.h b/shared/src/Agent.h index 1800451c84..7f0b4da2cf 100644 --- a/shared/src/Agent.h +++ b/shared/src/Agent.h @@ -10,19 +10,20 @@ #define __hifi__Agent__ #include -#include "AgentSocket.h" #include "AgentData.h" +#include class Agent { public: Agent(); - Agent(AgentSocket *agentPublicSocket, AgentSocket *agentLocalSocket, char agentType); + Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agentType); Agent(const Agent &otherAgent); Agent& operator=(Agent otherAgent); + bool operator==(const Agent& otherAgent); ~Agent(); - bool matches(AgentSocket *otherPublicSocket, AgentSocket *otherLocalSocket, char otherAgentType); - AgentSocket *publicSocket, *localSocket, *activeSocket; + bool matches(sockaddr *otherPublicSocket, sockaddr *otherLocalSocket, char otherAgentType); + sockaddr *publicSocket, *localSocket, *activeSocket; char type; timeval pingStarted; int pingMsecs; diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index a885405f61..f10d08fe27 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -16,28 +16,58 @@ UDPSocket * AgentList::getAgentSocket() { return &agentSocket; } +void AgentList::processAgentData(sockaddr *senderAddress, char *packetData, size_t dataBytes) { + switch (packetData[0]) { + case 'D': + { + // list of agents from domain server + updateList(packetData); + break; + } + case 'P': + { + // ping from another agent + char reply[] = "R"; + agentSocket.send(senderAddress, reply, 1); + break; + } + case 'R': + { + // ping reply from another agent + handlePingReply(senderAddress); + break; + } + } +} + int AgentList::updateList(char *packetData) { int readAgents = 0; int scannedItems = 0; char agentType; - AgentSocket agentPublicSocket = AgentSocket(); - AgentSocket agentLocalSocket = AgentSocket(); + + // 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; + + Agent newAgent; while((scannedItems = sscanf(packetData, - "%c %s %hd %s %hd,", + "%c %u %hd %u %hd,", &agentType, - agentPublicSocket.address, - &agentPublicSocket.port, - agentLocalSocket.address, - &agentLocalSocket.port + &agentPublicSocket->sin_addr.s_addr, + &agentPublicSocket->sin_port, + &agentLocalSocket->sin_addr.s_addr, + &agentLocalSocket->sin_port ))) { std::vector::iterator agent; for(agent = agents.begin(); agent != agents.end(); agent++) { - if (agent->matches(&agentPublicSocket, &agentLocalSocket, agentType)) { + if (agent->matches((sockaddr *)&agentPublicSocket, (sockaddr *)&agentLocalSocket, agentType)) { // we already have this agent, stop checking break; } @@ -45,7 +75,7 @@ int AgentList::updateList(char *packetData) { if (agent == agents.end()) { // we didn't have this agent, so add them - newAgent = Agent(&agentPublicSocket, &agentLocalSocket, agentType); + newAgent = Agent((sockaddr *)agentPublicSocket, (sockaddr *)agentLocalSocket, agentType); std::cout << "Added new agent - PS: " << agentPublicSocket << " LS: " << agentLocalSocket << " AT: " << agentType << "\n"; agents.push_back(newAgent); } else { @@ -64,7 +94,7 @@ void AgentList::pingAgents() { if (agent->activeSocket != NULL) { // we know which socket is good for this agent, send there - agentSocket.send(agent->activeSocket, payload, 1); + agentSocket.send((sockaddr *)agent->activeSocket, payload, 1); } else { // ping both of the sockets for the agent so we can figure out // which socket we can use @@ -72,4 +102,24 @@ void AgentList::pingAgents() { agentSocket.send(agent->localSocket, payload, 1); } } +} + +void AgentList::handlePingReply(sockaddr *agentAddress) { + for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { + // check both the public and local addresses for each agent to see if we find a match + // prioritize the private address so that we prune erroneous local matches + sockaddr *matchedSocket = NULL; + + if (socketMatch(agent->publicSocket, agentAddress)) { + matchedSocket = agent->publicSocket; + } else if (socketMatch(agent->localSocket, agentAddress)) { + matchedSocket = agent->localSocket; + } + + if (matchedSocket != NULL) { + // matched agent, stop checking + // update the agent's ping + break; + } + } } \ No newline at end of file diff --git a/shared/src/AgentList.h b/shared/src/AgentList.h index d98da3ea4d..b1be10324c 100644 --- a/shared/src/AgentList.h +++ b/shared/src/AgentList.h @@ -21,16 +21,15 @@ class AgentList { AgentList(); std::vector agents; int updateList(char *packetData); - - int processAgentData(char *address, unsigned short port, char *packetData, size_t dataBytes); + void processAgentData(sockaddr *senderAddress, char *packetData, size_t dataBytes); + int broadcastToAgents(char *broadcastData, size_t dataBytes, bool sendToSelf); void pingAgents(); UDPSocket* getAgentSocket(); private: UDPSocket agentSocket; - int addAgent(AgentSocket *publicSocket, AgentSocket *localSocket, char agentType); - int indexOfMatchingAgent(AgentSocket *publicSocket, AgentSocket *privateSocket, char agentType); - + int addAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType); + void handlePingReply(sockaddr *agentAddress); }; #endif /* defined(__hifi__AgentList__) */ diff --git a/shared/src/AgentSocket.cpp b/shared/src/AgentSocket.cpp deleted file mode 100644 index 6a7a7ab852..0000000000 --- a/shared/src/AgentSocket.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// 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=(AgentSocket otherAgentSocket) { - swap(*this, otherAgentSocket); - return *this; -} - -void AgentSocket::swap(AgentSocket &first, AgentSocket &second) { - using std::swap; - - swap(first.address, second.address); - swap(first.port, second.port); -} - -AgentSocket::~AgentSocket() { - delete address; -} - diff --git a/shared/src/AgentSocket.h b/shared/src/AgentSocket.h deleted file mode 100644 index ee460977fe..0000000000 --- a/shared/src/AgentSocket.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// 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=(AgentSocket otherAgentSocket); - ~AgentSocket(); - - char *address; - unsigned short port; - private: - void swap(AgentSocket &first, AgentSocket &second); -}; - -inline std::ostream& operator<<(std::ostream & Str, AgentSocket const &socket) { - Str << socket.address << ":" << socket.port; - return Str; -} - -#endif /* defined(__hifi__AgentSocket__) */ diff --git a/shared/src/UDPSocket.cpp b/shared/src/UDPSocket.cpp index 4c1df52b2b..1cac63a985 100644 --- a/shared/src/UDPSocket.cpp +++ b/shared/src/UDPSocket.cpp @@ -16,6 +16,26 @@ sockaddr_in destSockaddr, senderAddress; +bool socketMatch(sockaddr *first, sockaddr *second) { + // utility function that indicates if two sockets are equivalent + + // currently only compares two IPv4 addresses + // expandable to IPv6 by adding else if for AF_INET6 + + if (first->sa_family != second->sa_family) { + // not the same family, can't be equal + return false; + } else if (first->sa_family == AF_INET) { + sockaddr_in *firstIn = (sockaddr_in *) first; + sockaddr_in *secondIn = (sockaddr_in *) second; + + return firstIn->sin_addr.s_addr == secondIn->sin_addr.s_addr + && firstIn->sin_port == secondIn->sin_port; + } else { + return false; + } +} + UDPSocket::UDPSocket(int listeningPort) { // create the socket handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); @@ -48,21 +68,21 @@ UDPSocket::~UDPSocket() { // Receive data on this socket with retrieving address of sender bool UDPSocket::receive(void *receivedData, ssize_t *receivedBytes) { - return receive(&senderAddress, receivedData, receivedBytes); + return receive((sockaddr *)&senderAddress, receivedData, receivedBytes); } // Receive data on this socket with the address of the sender -bool UDPSocket::receive(sockaddr_in *recvAddress, void *receivedData, ssize_t *receivedBytes) { +bool UDPSocket::receive(sockaddr *recvAddress, void *receivedData, ssize_t *receivedBytes) { socklen_t addressSize = sizeof(&recvAddress); *receivedBytes = recvfrom(handle, receivedData, MAX_BUFFER_LENGTH_BYTES, - 0, (sockaddr *) recvAddress, &addressSize); + 0, recvAddress, &addressSize); return (*receivedBytes > 0); } -int UDPSocket::send(sockaddr_in *destAddress, const void *data, size_t byteLength) { +int UDPSocket::send(sockaddr *destAddress, const void *data, size_t byteLength) { // send data via UDP int sent_bytes = sendto(handle, (const char*)data, byteLength, @@ -82,12 +102,5 @@ int UDPSocket::send(char * destAddress, int destPort, const void *data, size_t b destSockaddr.sin_addr.s_addr = inet_addr(destAddress); destSockaddr.sin_port = htons((uint16_t)destPort); - return send(&destSockaddr, data, byteLength); -} - -int UDPSocket::send(AgentSocket *destAgentSocket, const void *data, size_t byteLength) { - destSockaddr.sin_addr.s_addr = inet_addr(destAgentSocket->address); - destSockaddr.sin_port = htons(destAgentSocket->port); - - return send(&destSockaddr, data, byteLength); + return send((sockaddr *)&destSockaddr, data, byteLength); } diff --git a/shared/src/UDPSocket.h b/shared/src/UDPSocket.h index 973c942d81..47ff8ffaee 100644 --- a/shared/src/UDPSocket.h +++ b/shared/src/UDPSocket.h @@ -12,7 +12,6 @@ #include #include #include -#include "AgentSocket.h" #define MAX_BUFFER_LENGTH_BYTES 1024 @@ -20,13 +19,14 @@ class UDPSocket { public: UDPSocket(int listening_port); ~UDPSocket(); - int send(sockaddr_in *destAddress, const void *data, size_t byteLength); + int send(sockaddr *destAddress, const void *data, size_t byteLength); int send(char *destAddress, int destPort, const void *data, size_t byteLength); - int send(AgentSocket *destAgentSocket, const void *data, size_t byteLength); bool receive(void *receivedData, ssize_t *receivedBytes); - bool receive(sockaddr_in *recvAddress, void *receivedData, ssize_t *receivedBytes); + bool receive(sockaddr *recvAddress, void *receivedData, ssize_t *receivedBytes); private: int handle; }; +bool socketMatch(sockaddr *first, sockaddr *second); + #endif /* defined(__interface__UDPSocket__) */