SingleHostUnderlayConfigurator.cc

Go to the documentation of this file.
00001 //
00002 // This program is free software; you can redistribute it and/or
00003 // modify it under the terms of the GNU General Public License
00004 // as published by the Free Software Foundation; either version 2
00005 // of the License, or (at your option) any later version.
00006 //
00007 // This program is distributed in the hope that it will be useful,
00008 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00009 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010 // GNU General Public License for more details.
00011 //
00012 // You should have received a copy of the GNU General Public License
00013 // along with this program; if not, write to the Free Software
00014 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00015 //
00016 
00024 #include <stdio.h>
00025 #include <unistd.h>
00026 #include <fcntl.h>
00027 
00028 #define WANT_WINSOCK2
00029 #include <platdep/sockets.h>
00030 
00031 #ifndef _WIN32
00032 #include <net/if.h>
00033 #include <sys/ioctl.h>
00034 #include <arpa/inet.h>
00035 #include <netinet/in.h>
00036 #endif
00037 
00038 #include <stun/stun_udp.h>
00039 #include <stun/stun.h>
00040 
00041 #include <omnetpp.h>
00042 
00043 #include "IInterfaceTable.h"
00044 #include "InterfaceEntry.h"
00045 #include "IPv4InterfaceData.h"
00046 #include "IPAddressResolver.h"
00047 
00048 #include <PeerInfo.h>
00049 #include <IRoutingTable.h>
00050 #include <NodeHandle.h>
00051 #include <GlobalNodeListAccess.h>
00052 
00053 #include "SingleHostUnderlayConfigurator.h"
00054 
00055 Define_Module(SingleHostUnderlayConfigurator);
00056 
00057 void SingleHostUnderlayConfigurator::initializeUnderlay(int stage)
00058 {
00059     StunAddress4 publicAddr, stunServerAddr;
00060     IPvXAddress addr;
00061 
00062     if(stage != MAX_STAGE_UNDERLAY)
00063         return;
00064 
00065     overlayTerminalCount = 1;
00066 
00067     // Set IP, Routes, etc
00068     cModule* node = getParentModule()->getSubmodule("overlayTerminal", 0);
00069 
00070     std::string nodeInterface = std::string(par("nodeInterface").stringValue());
00071     std::string stunServer = std::string(par("stunServer").stringValue());
00072     std::string nodeIP = std::string(par("nodeIP").stringValue());
00073 
00074     if (!nodeInterface.size() && !stunServer.size() && !nodeIP.size()) {
00075         throw cRuntimeError("SingleHostConfigurator::initializeUnderlay(): "
00076                             "Please specify at least one of "
00077                             "**.nodeInterface, **.nodeIP, or **.stunServer");
00078     }
00079 
00080     if (nodeInterface.size()) {
00081 #ifndef _WIN32
00082         SOCKET sock_fd;
00083         struct ifreq req;
00084         if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) !=
00085             INVALID_SOCKET) {
00086 
00087             snprintf(req.ifr_name, sizeof(req.ifr_name), "%s", nodeInterface.c_str());
00088 
00089             if (!ioctl(sock_fd, SIOCGIFADDR, &req)) {
00090                 addr = IPAddress(inet_ntoa(((struct sockaddr_in *)
00091                         (&req.ifr_addr))->sin_addr));
00092             } else {
00093                 throw cRuntimeError("SingleHostConfigurator::"
00094                                         "initializeUnderlay(): "
00095                                         "Invalid interface!");
00096             }
00097             close(sock_fd);
00098         }
00099 #else
00100         throw cRuntimeError("SingleHostConfigurator::"
00101                 "initializeUnderlay(): "
00102                 "**.nodeInterface parameter not supported on WIN32 yet!");
00103 #endif
00104     } else if (nodeIP.size()) {
00105         addr = IPAddress(nodeIP.c_str());
00106     }
00107 
00108     if (stunServer.size()) {
00109         // TODO: use and set overlayPort!
00110         throw cRuntimeError("SingleHostConfigurator::initializeUnderlay():"
00111                                 " Not implemented yet!");
00112         int srcPort = 0;
00113         publicAddr.addr = 0;
00114         publicAddr.port = srcPort;
00115         stunServerAddr.addr = 0;
00116         char tmpAddr[512];
00117         strncpy (tmpAddr, stunServer.c_str(), 512);
00118 
00119         if (stunParseServerName(tmpAddr, stunServerAddr)) {
00120             bool presPort = false;
00121             bool hairpin = false;
00122 
00123             NatType stype = stunNatType(stunServerAddr, false, &presPort,
00124                                         &hairpin, srcPort, &publicAddr);
00125             if (stype != StunTypeOpen) {
00126                 EV << "SingleHostConfigurator::initializeUnderlay(): "
00127                    << "Node is behind NAT or invalid STUN server configuration!"
00128                    << std::endl;
00129             }
00130 
00131             publicAddr.addr = htonl(publicAddr.addr);
00132             addr = IPAddress(inet_ntoa(*((struct in_addr *)(&(publicAddr.addr)))));
00133         }
00134     }
00135 
00136     IPvXAddress gw = addr;
00137     InterfaceEntry* ifEntry = IPAddressResolver().interfaceTableOf(node)->
00138             getInterfaceByName("outDev");
00139     IRoutingTable* rTable = check_and_cast<IRoutingTable*>(node->getSubmodule("routingTable", 0));
00140 
00141     ifEntry->ipv4Data()->setIPAddress(addr.get4());
00142     ifEntry->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS);
00143 
00144     IPRoute* te = new IPRoute();
00145     te->setHost(IPAddress::UNSPECIFIED_ADDRESS);
00146     te->setNetmask(IPAddress::UNSPECIFIED_ADDRESS);
00147     te->setGateway(gw.get4());
00148     te->setInterface(ifEntry);
00149     te->setType(IPRoute::REMOTE);
00150     te->setSource(IPRoute::MANUAL);
00151     rTable->addRoute(te);
00152 
00153     //add node to bootstrap oracle
00154     PeerInfo* info = new PeerInfo(0, node->getId(), NULL);
00155     globalNodeList->addPeer(addr, info);
00156 
00157     if (strlen(par("bootstrapIP")) > 0) {
00158         PeerInfo* bootstrapInfo = new PeerInfo(0, -1, NULL);
00159         globalNodeList->addPeer(IPAddress(par("bootstrapIP").stringValue()),
00160                                 bootstrapInfo);
00161 
00162         globalNodeList->registerPeer(NodeHandle(OverlayKey::ONE,
00163             IPAddress(par("bootstrapIP").stringValue()), par("bootstrapPort")));
00164     }
00165 
00166     // update display
00167     setDisplayString();
00168 
00169     scheduleAt(simTime(), new cMessage("init phase finished"));
00170 }
00171 void SingleHostUnderlayConfigurator::handleTimerEvent(cMessage* msg)
00172 {
00173     if (std::string(msg->getName()) != "init phase finished") {
00174         throw cRuntimeError("unknown self-message received");
00175     }
00176     delete msg;
00177 
00178     initFinished();
00179 }
00180 
00181 void SingleHostUnderlayConfigurator::setDisplayString()
00182 {
00183     // updates the statistics display string
00184     char buf[80];
00185     sprintf(buf, "%i overlay terminals", overlayTerminalCount);
00186     getDisplayString().setTagArg("t", 0, buf);
00187 }
00188 
00189 void SingleHostUnderlayConfigurator::finishUnderlay()
00190 {
00191     if (!isInInitPhase()) {
00192         struct timeval now, diff;
00193         gettimeofday(&now, NULL);
00194         timersub(&now, &initFinishedTime, &diff);
00195         printf("Simulation time: %li.%06li\n", diff.tv_sec, diff.tv_usec);
00196     }
00197 }
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3