OverSim
udpoutscheduler.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 
24 #include "udpoutscheduler.h"
25 #include "IPvXAddress.h"
26 #include <regmacros.h>
27 
29 
30 // Note: this is defined in tunoutscheduler.cc
31 extern cConfigOption *CFGID_EXTERNALAPP_APP_PORT;
32 
34 {
35  if (additional_fd >= 0) {
36 #ifdef _WIN32
37  closesocket(additional_fd);
38 #else
39  close(additional_fd);
40 #endif
41  }
42 }
43 
45 {
46  // get app port (0 if external app is not used)
47  int appPort = ev.getConfig()->getAsInt(CFGID_EXTERNALAPP_APP_PORT, 0);
48 
49  // Initialize TCP socket for App communication if desired
50  if (appPort > 0) {
51 
52  struct sockaddr_in server;
53  SOCKET sock;
54 
55  // Waiting for a TCP connection
56  sock = socket(AF_INET, SOCK_STREAM, 0);
57 
58  if (sock == INVALID_SOCKET) {
59  opp_error("Error creating socket");
60  return -1;
61  }
62 
63  int on = 1;
64  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
65 
66  memset(&server, 0, sizeof (server));
67  server.sin_family = AF_INET;
68  server.sin_addr.s_addr = htonl(INADDR_ANY);
69  server.sin_port = htons(appPort);
70 
71  if (bind( sock, (struct sockaddr*)&server, sizeof( server)) < 0) {
72  opp_error("Error binding to app socket");
73  return -1;
74  }
75 
76  if (listen( sock, 5 ) == -1) {
77  opp_error("Error listening on app socket");
78  return -1;
79  }
80  // Set additional_fd so we will be called if data
81  // (i.e. connection requests) is available at sock
82  additional_fd = sock;
83  FD_SET(additional_fd, &all_fds);
84  if (additional_fd > maxfd) {
86  }
87  }
88 
89  // Open UDP port
90  if (netw_fd != INVALID_SOCKET) {
91  // Port is already open, reuse it...
92  FD_SET(netw_fd, &all_fds);
93 
94  if (netw_fd> maxfd) {
95  maxfd = netw_fd;
96  }
97 
98  return 0;
99  }
100 
101  sockaddr_in addr;
102  netw_fd = socket(AF_INET, SOCK_DGRAM, 0);
103  memset(&addr, 0, sizeof(addr));
104  addr.sin_family = AF_INET;
105 
106  cModule* overlay = simulation.getModuleByPath(
107  "SingleHostUnderlayNetwork.overlayTerminal[0].overlay");
108 
109  if (overlay == NULL) {
110  throw cRuntimeError("UdpOutScheduler::initializeNetwork(): "
111  "Overlay module not found!");
112  }
113 
114  addr.sin_port = htons(overlay->gate("appIn")->getNextGate()->
115  getOwnerModule()->par("localPort").longValue());
116 
117  cModule* underlayConfigurator =
118  simulation.getModuleByPath("SingleHostUnderlayNetwork.underlayConfigurator");
119 
120  if (underlayConfigurator == NULL) {
121  throw cRuntimeError("UdpOutScheduler::initializeNetwork(): "
122  "UnderlayConfigurator module not found!");
123  }
124 
125  if (strlen(underlayConfigurator->par("nodeIP").stringValue())) {
126  addr.sin_addr.s_addr = htonl(IPAddress(underlayConfigurator->
127  par("nodeIP").stringValue()).getInt());
128  } else {
129  addr.sin_addr.s_addr = htonl(INADDR_ANY);
130  }
131 
132  if (bind( netw_fd, (sockaddr*)&addr, sizeof(addr)) < 0) {
133  opp_error("Error binding to UDP socket");
134  return -1;
135  }
136 
137  FD_SET(netw_fd, &all_fds);
138 
139  if (netw_fd> maxfd) {
140  maxfd = netw_fd;
141  }
142 
143  return 0;
144 }
145 
147  sockaddr* from = (sockaddr*) new sockaddr_in;
148  socklen_t addrlen = sizeof(sockaddr_in);
149 
150  SOCKET new_sock = accept( additional_fd, from, &addrlen );
151 
152  if (new_sock == INVALID_SOCKET) {
153  opp_warning("Error connecting to remote app");
154  return;
155  }
156 
157  if (appConnectionLimit) {
158  int count = 0;
159 
160  for (SOCKET fd = 0; fd <= maxfd; fd++) {
161  if (fd == netw_fd) continue;
162  if (fd == additional_fd) continue;
163  if (FD_ISSET(fd, &all_fds)) count++;
164  }
165 
166  if (count >= appConnectionLimit) {
167  // We already have too many connections to external applications
168  // "reject" connection
169 #ifdef _WIN32
170  closesocket(new_sock);
171 #else
172  close(new_sock);
173 #endif
174  ev << "[UdpOutScheduler::additionalFD()]\n"
175  << " Rejecting new app connection (FD: " << new_sock << ")"
176  << endl;
177 
178  return;
179  }
180  }
181 
182  FD_SET(new_sock, &all_fds);
183 
184  if (new_sock > maxfd) {
185  maxfd = new_sock;
186  }
187 
188  // Inform app about new connection
189  appPacketBuffer->push_back(PacketBufferEntry(0, 0, from, addrlen,
191 
193 
194  ev << "[UdpOutScheduler::additionalFD()]\n"
195  << " Accepting new app connection (FD: " << new_sock << ")"
196  << endl;
197 }