a bad version of UDP hole punching for local agents

This commit is contained in:
Stephen Birarda 2013-02-18 08:53:16 -08:00
parent b05909cf00
commit d1433aa2bd
4 changed files with 111 additions and 56 deletions

View file

@ -42,8 +42,10 @@ const int LOGOFF_CHECK_INTERVAL = 5000;
struct AgentList { struct AgentList {
char agentType; char agentType;
uint32_t ip; uint32_t ip;
in_addr sin_addr; in_addr public_sin_addr;
in_port_t port; in_port_t public_port;
char *private_addr;
in_port_t private_port;
float x, y, z; float x, y, z;
bool active; bool active;
timeval time, connectTime; timeval time, connectTime;
@ -61,11 +63,11 @@ double diffclock(timeval clock1,timeval clock2)
return diffms; return diffms;
} }
int addAgent(uint32_t ip, in_port_t port, char agentType, float x, float y, float z) { 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 // Search for agent in list and add if needed
int i = 0; int i = 0;
int is_new = 0; int is_new = 0;
while ((ip != agents[i].ip || port != agents[i].port) && (i < num_agents)) { while ((ip != agents[i].ip || port != agents[i].public_port) && (i < num_agents)) {
i++; i++;
} }
if ((i == num_agents) || (agents[i].active == false)) is_new = 1; if ((i == num_agents) || (agents[i].active == false)) is_new = 1;
@ -74,8 +76,10 @@ int addAgent(uint32_t ip, in_port_t port, char agentType, float x, float y, floa
agents[i].y = y; agents[i].y = y;
agents[i].z = z; agents[i].z = z;
agents[i].active = true; agents[i].active = true;
agents[i].sin_addr.s_addr = ip; agents[i].public_sin_addr.s_addr = ip;
agents[i].port = port; agents[i].public_port = port;
agents[i].private_addr = private_ip;
agents[i].private_port = private_port;
agents[i].agentType = agentType; agents[i].agentType = agentType;
gettimeofday(&agents[i].time, NULL); gettimeofday(&agents[i].time, NULL);
if (is_new) gettimeofday(&agents[i].connectTime, NULL); if (is_new) gettimeofday(&agents[i].connectTime, NULL);
@ -92,7 +96,7 @@ void update_agent_list(timeval now) {
if ((diffclock(agents[i].time, now) > LOGOFF_CHECK_INTERVAL) && if ((diffclock(agents[i].time, now) > LOGOFF_CHECK_INTERVAL) &&
agents[i].active) { agents[i].active) {
std::cout << "Expired Agent type " << agents[i].agentType << " from " << std::cout << "Expired Agent type " << agents[i].agentType << " from " <<
inet_ntoa(agents[i].sin_addr) << ":" << agents[i].port << "\n"; inet_ntoa(agents[i].public_sin_addr) << ":" << agents[i].public_port << "\n";
agents[i].active = false; agents[i].active = false;
} }
} }
@ -102,8 +106,10 @@ void send_agent_list(sockaddr_in *agentAddrPointer) {
int i, length = 0; int i, length = 0;
ssize_t sentBytes; ssize_t sentBytes;
char buffer[MAX_PACKET_SIZE]; char buffer[MAX_PACKET_SIZE];
char * address; char * public_address;
char portstring[10]; char public_portstring[10];
char * private_address;
char private_portstring[10];
int numSent = 0; int numSent = 0;
buffer[length++] = 'D'; buffer[length++] = 'D';
//std::cout << "send list to: " << inet_ntoa(dest_address->sin_addr) << "\n"; //std::cout << "send list to: " << inet_ntoa(dest_address->sin_addr) << "\n";
@ -111,21 +117,31 @@ void send_agent_list(sockaddr_in *agentAddrPointer) {
if (agents[i].active) { if (agents[i].active) {
// Write the type of the agent // Write the type of the agent
buffer[length++] = agents[i].agentType; buffer[length++] = agents[i].agentType;
// Write agent's IP address // Write agent's public IP address
address = inet_ntoa(agents[i].sin_addr); public_address = inet_ntoa(agents[i].public_sin_addr);
memcpy(&buffer[length], address, strlen(address)); memcpy(&buffer[length], public_address, strlen(public_address));
length += strlen(address); length += strlen(public_address);
// Add port number // Add public port number
buffer[length++] = ' '; buffer[length++] = ' ';
sprintf(portstring, "%d\n", agents[i].port); sprintf(public_portstring, "%hd", agents[i].public_port);
memcpy(&buffer[length], portstring, strlen(portstring)); memcpy(&buffer[length], public_portstring, strlen(public_portstring));
length += strlen(portstring); length += strlen(public_portstring);
// Add comma separator between agents // Write agent's private IP address
buffer[length++] = ','; 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++; numSent++;
} }
} }
std::cout << "The sent buffer was " << buffer << "\n";
if (length > 1) { if (length > 1) {
sentBytes = domainSocket.send(agentAddrPointer, buffer, length); sentBytes = domainSocket.send(agentAddrPointer, buffer, length);
@ -150,11 +166,14 @@ int main(int argc, const char * argv[])
while (true) { while (true) {
if (domainSocket.receive(&agentAddress, packet_data, &receivedBytes)) { if (domainSocket.receive(&agentAddress, packet_data, &receivedBytes)) {
float x,y,z; float x,y,z;
char agentType; char agentType;
sscanf(packet_data, "%c %f,%f,%f", &agentType, &x, &y, &z); char private_ip[50];
if (addAgent(agentAddress.sin_addr.s_addr, ntohs(agentAddress.sin_port), agentType, x, y, z)) { 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 " << std::cout << "Added Agent, type " << agentType << " from " <<
inet_ntoa(agentAddress.sin_addr) << ":" << ntohs(agentAddress.sin_port) << "\n"; inet_ntoa(agentAddress.sin_addr) << ":" << ntohs(agentAddress.sin_port) <<
" (" << private_ip << ":" << private_port << ")" << "\n";
} }
// Reply with packet listing nearby active agents // Reply with packet listing nearby active agents
send_agent_list(&agentAddress); send_agent_list(&agentAddress);

View file

@ -16,8 +16,12 @@
const int MAX_AGENTS = 100; const int MAX_AGENTS = 100;
struct AgentList { struct AgentList {
char address[255]; char public_address[255];
unsigned short port; unsigned short public_port;
char private_address[255];
unsigned short private_port;
char *goodAddress = NULL;
unsigned short goodPort;
timeval pingStarted; timeval pingStarted;
int pingMsecs; int pingMsecs;
char agentType; char agentType;
@ -29,7 +33,7 @@ int num_agents = 0;
char * getAgentAddress(int agentNumber) { char * getAgentAddress(int agentNumber) {
if (agentNumber < getAgentCount()) return agents[agentNumber].address; if (agentNumber < getAgentCount()) return agents[agentNumber].public_address;
else return NULL; else return NULL;
} }
@ -51,17 +55,15 @@ int update_agents(char * data, int length) {
std::string packet(data, length); std::string packet(data, length);
size_t spot; size_t spot;
size_t start_spot = 0; size_t start_spot = 0;
std::string address, port; char *public_address = new char[255];
char *private_address = new char[255];
char agentType; char agentType;
unsigned short nPort = 0; unsigned short public_port, private_port;
unsigned int iPort = 0;
spot = packet.find_first_of (",", 0); spot = packet.find_first_of (",", 0);
while (spot != std::string::npos) { while (spot != std::string::npos) {
std::string thisAgent = packet.substr(start_spot, spot-start_spot); std::string thisAgent = packet.substr(start_spot, spot-start_spot);
//std::cout << "raw string: " << thisAgent << "\n"; sscanf(thisAgent.c_str(), "%c %s %hd %s %hd", &agentType, public_address, &public_port, private_address, &private_port);
sscanf(thisAgent.c_str(), "%c %s %u", &agentType, address.c_str(), &iPort); add_agent(public_address, public_port, private_address, private_port, agentType);
nPort = (unsigned short) iPort;
add_agent((char *)address.c_str(), nPort, agentType);
numAgents++; numAgents++;
start_spot = spot + 1; start_spot = spot + 1;
if (start_spot < packet.length()) if (start_spot < packet.length())
@ -91,7 +93,7 @@ void update_agent(char * address, unsigned short port, char * data, int length)
{ {
//printf("%s:%d\n", address, port); //printf("%s:%d\n", address, port);
for (int i = 0; i < num_agents; i++) { for (int i = 0; i < num_agents; i++) {
if ((strcmp(address, agents[i].address) == 0) && (agents[i].port == port)) { if ((strcmp(address, agents[i].public_address) == 0) && (agents[i].public_port == port)) {
// Update the agent // Update the agent
agents[i].head.recvBroadcastData(data, length); agents[i].head.recvBroadcastData(data, length);
if ((strcmp(address, "127.0.0.1") == 0) && (port == AGENT_UDP_PORT)) { if ((strcmp(address, "127.0.0.1") == 0) && (port == AGENT_UDP_PORT)) {
@ -104,21 +106,23 @@ void update_agent(char * address, unsigned short port, char * data, int length)
// //
// Look for an agent by it's IP number, add if it does not exist in local list // 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 agentType) { int add_agent(char * address, unsigned short port, char *private_address, unsigned short private_port, char agentType) {
//std::cout << "Checking for " << IP->c_str() << " "; //std::cout << "Checking for " << IP->c_str() << " ";
for (int i = 0; i < num_agents; i++) { for (int i = 0; i < num_agents; i++) {
if ((strcmp(address, agents[i].address) == 0) && (agents[i].port == port)) { if ((strcmp(address, agents[i].public_address) == 0) && (agents[i].public_port == port)) {
//std::cout << "Found agent!\n"; //std::cout << "Found agent!\n";
return 0; return 0;
} }
} }
if (num_agents < MAX_AGENTS) { if (num_agents < MAX_AGENTS) {
strcpy(agents[num_agents].address, address); strcpy(agents[num_agents].public_address, address);
agents[num_agents].port = port; agents[num_agents].public_port = port;
agents[num_agents].agentType = agentType; agents[num_agents].agentType = agentType;
strcpy(agents[num_agents].private_address, private_address);
agents[num_agents].private_port = private_port;
std::cout << "Added Agent # " << num_agents << " with Address " << std::cout << "Added Agent # " << num_agents << " with Address " <<
agents[num_agents].address << ":" << agents[num_agents].port << " T: " << agents[num_agents].public_address << ":" << agents[num_agents].public_port << " T: " <<
agentType << "\n"; agentType << " (" << agents[num_agents].private_address << ":" << agents[num_agents].private_port << ")\n";
num_agents++; num_agents++;
return 1; return 1;
@ -134,19 +138,16 @@ int add_agent(char * address, unsigned short port, char agentType) {
int broadcastToAgents(UDPSocket *handle, char * data, int length, int sendToSelf) { int broadcastToAgents(UDPSocket *handle, char * data, int length, int sendToSelf) {
int sent_bytes; int sent_bytes;
//printf("broadcasting to %d agents\n", num_agents); //printf("broadcasting to %d agents\n", num_agents);
for (int i = 0; i < num_agents; i++) { for (int i = 0; i < num_agents; i++) {
if (sendToSelf || (((strcmp((char *)"127.0.0.1", agents[i].address) != 0) if (agents[i].agentType != 'M' && agents[i].goodAddress != NULL) {
&& (agents[i].port != AGENT_UDP_PORT)))) // std::cout << "broadcasting my agent data to: " << agents[i].goodAddress << " : " << agents[i].goodPort << "\n";
if (agents[i].agentType != 'M') { sent_bytes = handle->send(agents[i].goodAddress, agents[i].goodPort, data, length);
//std::cout << "broadcasting my agent data to: " << agents[i].address << " : " << agents[i].port << "\n"; if (sent_bytes != length) {
std::cout << "Broadcast to agents FAILED\n";
sent_bytes = handle->send(agents[i].address, agents[i].port, data, length); return 0;
if (sent_bytes != length) {
std::cout << "Broadcast to agents FAILED\n";
return 0;
}
} }
}
} }
return 1; return 1;
} }
@ -157,7 +158,12 @@ void pingAgents(UDPSocket *handle) {
for (int i = 0; i < num_agents; i++) { for (int i = 0; i < num_agents; i++) {
if (agents[i].agentType != 'M') { if (agents[i].agentType != 'M') {
gettimeofday(&agents[i].pingStarted, NULL); gettimeofday(&agents[i].pingStarted, NULL);
handle->send(agents[i].address, agents[i].port, payload, 1); 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); //printf("\nSent Ping at %d usecs\n", agents[i].pingStarted.tv_usec);
} }
@ -167,7 +173,19 @@ void pingAgents(UDPSocket *handle) {
// On receiving a ping reply, save that with the agent record // On receiving a ping reply, save that with the agent record
void setAgentPing(char * address, unsigned short port) { void setAgentPing(char * address, unsigned short port) {
for (int i = 0; i < num_agents; i++) { for (int i = 0; i < num_agents; i++) {
if ((strcmp(address, agents[i].address) == 0) && (agents[i].port == port)) { 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; timeval pingReceived;
gettimeofday(&pingReceived, NULL); gettimeofday(&pingReceived, NULL);
float pingMsecs = diffclock(&agents[i].pingStarted, &pingReceived); float pingMsecs = diffclock(&agents[i].pingStarted, &pingReceived);
@ -180,7 +198,7 @@ void setAgentPing(char * address, unsigned short port) {
void kludgyMixerUpdate(Audio audio) { void kludgyMixerUpdate(Audio audio) {
for (int i = 0; i < num_agents; i++) { for (int i = 0; i < num_agents; i++) {
if (agents[i].agentType == 'M') { if (agents[i].agentType == 'M') {
audio.updateMixerParams(agents[i].address, agents[i].port); audio.updateMixerParams(agents[i].public_address, agents[i].public_port);
} }
} }
} }

View file

@ -22,7 +22,7 @@
const int AGENT_UDP_PORT = 40103; const int AGENT_UDP_PORT = 40103;
int update_agents(char * data, int length); int update_agents(char * data, int length);
int add_agent(char * address, unsigned short port, char agentType); 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); int broadcastToAgents(UDPSocket * handle, char * data, int length, int sendToSelf);
void pingAgents(UDPSocket *handle); void pingAgents(UDPSocket *handle);
void setAgentPing(char * address, unsigned short port); void setAgentPing(char * address, unsigned short port);

View file

@ -24,6 +24,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <sys/time.h> #include <sys/time.h>
#include <pthread.h> #include <pthread.h>
#include <ifaddrs.h>
// These includes are for the serial port reading/writing // These includes are for the serial port reading/writing
#include <unistd.h> #include <unistd.h>
@ -82,6 +83,8 @@ int WIDTH = 1200;
int HEIGHT = 800; int HEIGHT = 800;
int fullscreen = 0; int fullscreen = 0;
char localAddressBuffer[INET_ADDRSTRLEN];
Oscilloscope audioScope(512,200,true); Oscilloscope audioScope(512,200,true);
#define HAND_RADIUS 0.25 // Radius of in-world 'hand' of you #define HAND_RADIUS 0.25 // Radius of in-world 'hand' of you
@ -228,7 +231,8 @@ void Timer(int extra)
// Send a message to the domainserver telling it we are ALIVE // Send a message to the domainserver telling it we are ALIVE
// //
char output[100]; char output[100];
sprintf(output, "%c %f,%f,%f", 'I', location[0], location[1], location[2]); sprintf(output, "%c %f,%f,%f,%s %hd", 'I', location[0], location[1], location[2], localAddressBuffer, (unsigned short) AGENT_UDP_PORT);
std::cout << "sending " << output << " to domain server\n";
int packet_size = strlen(output); int packet_size = strlen(output);
agentSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, output, packet_size); agentSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, output, packet_size);
@ -929,6 +933,20 @@ int main(int argc, char** argv)
// Create network socket and buffer // Create network socket and buffer
incomingPacket = new char[MAX_PACKET_SIZE]; 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);
}
}
// Lookup the IP address of things we have hostnames // Lookup the IP address of things we have hostnames
if (atoi(DOMAIN_IP) == 0) { if (atoi(DOMAIN_IP) == 0) {
struct hostent* pHostInfo; struct hostent* pHostInfo;