remove AgentSocket abstraction to use sockaddr struct

This commit is contained in:
Stephen Birarda 2013-02-20 11:44:35 -08:00
parent 42927ec602
commit 7205817476
9 changed files with 169 additions and 160 deletions

View file

@ -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);
// }
}
}

View file

@ -7,23 +7,32 @@
//
#include "Agent.h"
#include <arpa/inet.h>
#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);
}

View file

@ -10,19 +10,20 @@
#define __hifi__Agent__
#include <iostream>
#include "AgentSocket.h"
#include "AgentData.h"
#include <sys/socket.h>
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;

View file

@ -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<Agent>::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<Agent>::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;
}
}
}

View file

@ -21,16 +21,15 @@ class AgentList {
AgentList();
std::vector<Agent> 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__) */

View file

@ -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;
}

View file

@ -1,32 +0,0 @@
//
// AgentSocket.h
// hifi
//
// Created by Stephen Birarda on 2/19/13.
//
//
#ifndef __hifi__AgentSocket__
#define __hifi__AgentSocket__
#include <iostream>
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__) */

View file

@ -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);
}

View file

@ -12,7 +12,6 @@
#include <iostream>
#include <netinet/in.h>
#include <netdb.h>
#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__) */