udpoutscheduler.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include "udpoutscheduler.h"
00025 #include "IPvXAddress.h"
00026 #include <regmacros.h>
00027 
00028 Register_Class(UdpOutScheduler);
00029 
00030 // Note: this is defined in tunoutscheduler.cc
00031 extern cConfigOption *CFGID_EXTERNALAPP_APP_PORT;
00032 
00033 UdpOutScheduler::~UdpOutScheduler()
00034 {
00035     if (additional_fd >= 0) {
00036 #ifdef _WIN32
00037         closesocket(additional_fd);
00038 #else
00039         close(additional_fd);
00040 #endif
00041     }
00042 }
00043 
00044 int UdpOutScheduler::initializeNetwork()
00045 {
00046     // get app port (0 if external app is not used)
00047     int appPort = ev.getConfig()->getAsInt(CFGID_EXTERNALAPP_APP_PORT, 0);
00048 
00049     // Initialize TCP socket for App communication if desired
00050     if (appPort > 0) {
00051 
00052         struct sockaddr_in server;
00053         SOCKET sock;
00054 
00055         // Waiting for a TCP connection
00056         sock = socket(AF_INET, SOCK_STREAM, 0);
00057 
00058         if (sock == INVALID_SOCKET) {
00059             opp_error("Error creating socket");
00060             return -1;
00061         }
00062 
00063         int on = 1;
00064         setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
00065 
00066         memset(&server, 0, sizeof (server));
00067         server.sin_family = AF_INET;
00068         server.sin_addr.s_addr = htonl(INADDR_ANY);
00069         server.sin_port = htons(appPort);
00070 
00071         if (bind( sock, (struct sockaddr*)&server, sizeof( server)) < 0) {
00072             opp_error("Error binding to app socket");
00073             return -1;
00074         }
00075 
00076         if (listen( sock, 5 ) == -1) {
00077             opp_error("Error listening on app socket");
00078             return -1;
00079         }
00080         // Set additional_fd so we will be called if data
00081         // (i.e. connection requests) is available at sock
00082         additional_fd = sock;
00083         FD_SET(additional_fd, &all_fds);
00084         if (additional_fd > maxfd) {
00085             maxfd = additional_fd;
00086         }
00087     }
00088 
00089     // Open UDP port
00090     if (netw_fd != INVALID_SOCKET) {
00091         // Port is already open, reuse it...
00092         FD_SET(netw_fd, &all_fds);
00093 
00094         if (netw_fd> maxfd) {
00095             maxfd = netw_fd;
00096         }
00097 
00098         return 0;
00099     }
00100 
00101     sockaddr_in addr;
00102     netw_fd = socket(AF_INET, SOCK_DGRAM, 0);
00103     memset(&addr, 0, sizeof(addr));
00104     addr.sin_family = AF_INET;
00105 
00106     cModule* overlay = simulation.getModuleByPath(
00107             "SingleHostUnderlayNetwork.overlayTerminal[0].overlay");
00108 
00109     if (overlay == NULL) {
00110         throw cRuntimeError("UdpOutScheduler::initializeNetwork(): "
00111                                 "Overlay module not found!");
00112     }
00113 
00114     addr.sin_port = htons(overlay->gate("appIn")->getNextGate()->
00115                           getOwnerModule()->par("localPort").longValue());
00116 
00117     cModule* underlayConfigurator =
00118         simulation.getModuleByPath("SingleHostUnderlayNetwork.underlayConfigurator");
00119 
00120     if (underlayConfigurator == NULL) {
00121         throw cRuntimeError("UdpOutScheduler::initializeNetwork(): "
00122                                 "UnderlayConfigurator module not found!");
00123     }
00124 
00125     if (strlen(underlayConfigurator->par("nodeIP").stringValue())) {
00126         addr.sin_addr.s_addr = htonl(IPAddress(underlayConfigurator->
00127                                        par("nodeIP").stringValue()).getInt());
00128     } else {
00129         addr.sin_addr.s_addr = htonl(INADDR_ANY);
00130     }
00131 
00132     if (bind( netw_fd, (sockaddr*)&addr, sizeof(addr)) < 0) {
00133         opp_error("Error binding to UDP socket");
00134         return -1;
00135     }
00136 
00137     FD_SET(netw_fd, &all_fds);
00138 
00139     if (netw_fd> maxfd) {
00140         maxfd = netw_fd;
00141     }
00142 
00143     return 0;
00144 }
00145 
00146 void UdpOutScheduler::additionalFD() {
00147     sockaddr* from = (sockaddr*) new sockaddr_in;
00148     socklen_t addrlen = sizeof(sockaddr_in);
00149 
00150     SOCKET new_sock = accept( additional_fd, from, &addrlen );
00151 
00152     if (new_sock == INVALID_SOCKET) {
00153         opp_warning("Error connecting to remote app");
00154         return;
00155     }
00156 
00157     if (appConnectionLimit) {
00158         int count = 0;
00159 
00160         for (SOCKET fd = 0; fd <= maxfd; fd++) {
00161             if (fd == netw_fd) continue;
00162             if (fd == additional_fd) continue;
00163             if (FD_ISSET(fd, &all_fds)) count++;
00164         }
00165 
00166         if (count >= appConnectionLimit) {
00167             // We already have too many connections to external applications
00168             // "reject" connection
00169 #ifdef _WIN32
00170             closesocket(new_sock);
00171 #else
00172             close(new_sock);
00173 #endif
00174             ev << "[UdpOutScheduler::additionalFD()]\n"
00175                << "    Rejecting new app connection (FD: " << new_sock << ")"
00176                << endl;
00177 
00178             return;
00179         }
00180     }
00181 
00182     FD_SET(new_sock, &all_fds);
00183 
00184     if (new_sock > maxfd) {
00185         maxfd = new_sock;
00186     }
00187 
00188     // Inform app about new connection
00189     appPacketBuffer->push_back(PacketBufferEntry(0, 0, from, addrlen,
00190                                PacketBufferEntry::PACKET_FD_NEW, new_sock));
00191 
00192     sendNotificationMsg(appNotificationMsg, appModule);
00193 
00194     ev << "[UdpOutScheduler::additionalFD()]\n"
00195        << "    Accepting new app connection (FD: " << new_sock << ")"
00196        << endl;
00197 }
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3