From d1433aa2bd1d91cc23c469936ce6ab50a4d7cbfc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 18 Feb 2013 08:53:16 -0800 Subject: [PATCH] a bad version of UDP hole punching for local agents --- domain/src/main.cpp | 65 +++++++++++++++++++++------------ interface/src/Agent.cpp | 80 +++++++++++++++++++++++++---------------- interface/src/Agent.h | 2 +- interface/src/main.cpp | 20 ++++++++++- 4 files changed, 111 insertions(+), 56 deletions(-) diff --git a/domain/src/main.cpp b/domain/src/main.cpp index aa4d936e32..7a395c0f74 100644 --- a/domain/src/main.cpp +++ b/domain/src/main.cpp @@ -42,8 +42,10 @@ const int LOGOFF_CHECK_INTERVAL = 5000; struct AgentList { char agentType; uint32_t ip; - in_addr sin_addr; - in_port_t port; + in_addr public_sin_addr; + in_port_t public_port; + char *private_addr; + in_port_t private_port; float x, y, z; bool active; timeval time, connectTime; @@ -61,11 +63,11 @@ double diffclock(timeval clock1,timeval clock2) 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 int i = 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++; } 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].z = z; agents[i].active = true; - agents[i].sin_addr.s_addr = ip; - agents[i].port = port; + agents[i].public_sin_addr.s_addr = ip; + agents[i].public_port = port; + 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); @@ -92,7 +96,7 @@ void update_agent_list(timeval now) { 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].sin_addr) << ":" << agents[i].port << "\n"; + inet_ntoa(agents[i].public_sin_addr) << ":" << agents[i].public_port << "\n"; agents[i].active = false; } } @@ -102,8 +106,10 @@ void send_agent_list(sockaddr_in *agentAddrPointer) { int i, length = 0; ssize_t sentBytes; char buffer[MAX_PACKET_SIZE]; - char * address; - char portstring[10]; + 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"; @@ -111,21 +117,31 @@ void send_agent_list(sockaddr_in *agentAddrPointer) { if (agents[i].active) { // Write the type of the agent buffer[length++] = agents[i].agentType; - // Write agent's IP address - address = inet_ntoa(agents[i].sin_addr); - memcpy(&buffer[length], address, strlen(address)); - length += strlen(address); - // Add port number + // 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(portstring, "%d\n", agents[i].port); - memcpy(&buffer[length], portstring, strlen(portstring)); - length += strlen(portstring); - // Add comma separator between agents - 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); @@ -150,11 +166,14 @@ int main(int argc, const char * argv[]) while (true) { if (domainSocket.receive(&agentAddress, packet_data, &receivedBytes)) { float x,y,z; - char agentType; - sscanf(packet_data, "%c %f,%f,%f", &agentType, &x, &y, &z); - if (addAgent(agentAddress.sin_addr.s_addr, ntohs(agentAddress.sin_port), agentType, 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) << "\n"; + inet_ntoa(agentAddress.sin_addr) << ":" << ntohs(agentAddress.sin_port) << + " (" << private_ip << ":" << private_port << ")" << "\n"; } // Reply with packet listing nearby active agents send_agent_list(&agentAddress); diff --git a/interface/src/Agent.cpp b/interface/src/Agent.cpp index f92fffed30..78a6578b53 100644 --- a/interface/src/Agent.cpp +++ b/interface/src/Agent.cpp @@ -16,8 +16,12 @@ const int MAX_AGENTS = 100; struct AgentList { - char address[255]; - unsigned short port; + char public_address[255]; + unsigned short public_port; + char private_address[255]; + unsigned short private_port; + char *goodAddress = NULL; + unsigned short goodPort; timeval pingStarted; int pingMsecs; char agentType; @@ -29,7 +33,7 @@ int num_agents = 0; char * getAgentAddress(int agentNumber) { - if (agentNumber < getAgentCount()) return agents[agentNumber].address; + if (agentNumber < getAgentCount()) return agents[agentNumber].public_address; else return NULL; } @@ -51,17 +55,15 @@ int update_agents(char * data, int length) { std::string packet(data, length); size_t spot; size_t start_spot = 0; - std::string address, port; + char *public_address = new char[255]; + char *private_address = new char[255]; char agentType; - unsigned short nPort = 0; - unsigned int iPort = 0; + 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); - //std::cout << "raw string: " << thisAgent << "\n"; - sscanf(thisAgent.c_str(), "%c %s %u", &agentType, address.c_str(), &iPort); - nPort = (unsigned short) iPort; - add_agent((char *)address.c_str(), nPort, agentType); + 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()) @@ -91,7 +93,7 @@ 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].address) == 0) && (agents[i].port == port)) { + 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)) { @@ -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 // -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() << " "; 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"; return 0; } } if (num_agents < MAX_AGENTS) { - strcpy(agents[num_agents].address, address); - agents[num_agents].port = port; + 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; std::cout << "Added Agent # " << num_agents << " with Address " << - agents[num_agents].address << ":" << agents[num_agents].port << " T: " << - agentType << "\n"; + 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; @@ -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 sent_bytes; //printf("broadcasting to %d agents\n", num_agents); - for (int i = 0; i < num_agents; i++) { - if (sendToSelf || (((strcmp((char *)"127.0.0.1", agents[i].address) != 0) - && (agents[i].port != AGENT_UDP_PORT)))) + 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"; - if (agents[i].agentType != 'M') { - //std::cout << "broadcasting my agent data to: " << agents[i].address << " : " << agents[i].port << "\n"; - - sent_bytes = handle->send(agents[i].address, agents[i].port, data, length); - if (sent_bytes != length) { - std::cout << "Broadcast to agents FAILED\n"; - return 0; - } + 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; } @@ -157,7 +158,12 @@ void pingAgents(UDPSocket *handle) { for (int i = 0; i < num_agents; i++) { if (agents[i].agentType != 'M') { 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); } @@ -167,7 +173,19 @@ void pingAgents(UDPSocket *handle) { // 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++) { - 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; gettimeofday(&pingReceived, NULL); float pingMsecs = diffclock(&agents[i].pingStarted, &pingReceived); @@ -180,7 +198,7 @@ void setAgentPing(char * address, unsigned short port) { void kludgyMixerUpdate(Audio audio) { for (int i = 0; i < num_agents; i++) { if (agents[i].agentType == 'M') { - audio.updateMixerParams(agents[i].address, agents[i].port); + audio.updateMixerParams(agents[i].public_address, agents[i].public_port); } } } diff --git a/interface/src/Agent.h b/interface/src/Agent.h index 1df03dd017..15a363bb12 100644 --- a/interface/src/Agent.h +++ b/interface/src/Agent.h @@ -22,7 +22,7 @@ const int AGENT_UDP_PORT = 40103; 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); void pingAgents(UDPSocket *handle); void setAgentPing(char * address, unsigned short port); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 3ac243fca1..51c2558ed8 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -24,6 +24,7 @@ #include #include #include +#include // These includes are for the serial port reading/writing #include @@ -82,6 +83,8 @@ int WIDTH = 1200; int HEIGHT = 800; int fullscreen = 0; +char localAddressBuffer[INET_ADDRSTRLEN]; + Oscilloscope audioScope(512,200,true); #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 // 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); agentSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, output, packet_size); @@ -929,6 +933,20 @@ 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); + } + } + // Lookup the IP address of things we have hostnames if (atoi(DOMAIN_IP) == 0) { struct hostent* pHostInfo;