SingleHostUnderlayConfigurator.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
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
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
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
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 }