Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
SensorNetwork.cpp
00001 /************************************************************************************** 00002 * Copyright (c) 2016, Tomoaki Yamaguchi 00003 * 00004 * All rights reserved. This program and the accompanying materials 00005 * are made available under the terms of the Eclipse Public License v1.0 00006 * and Eclipse Distribution License v1.0 which accompany this distribution. 00007 * 00008 * The Eclipse Public License is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * and the Eclipse Distribution License is available at 00011 * http://www.eclipse.org/org/documents/edl-v10.php. 00012 * 00013 * Contributors: 00014 * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation 00015 **************************************************************************************/ 00016 #include <stdio.h> 00017 #include <unistd.h> 00018 #include <sys/types.h> 00019 #include <sys/socket.h> 00020 #include <netinet/ip.h> 00021 #include <arpa/inet.h> 00022 #include <netdb.h> 00023 #include <string.h> 00024 #include <regex> 00025 #include <string> 00026 #include <stdlib.h> 00027 #include "SensorNetwork.h" 00028 #include "MQTTSNGWProcess.h" 00029 00030 using namespace std; 00031 using namespace MQTTSNGW; 00032 00033 /*=========================================== 00034 Class SensorNetAddreess 00035 00036 These 4 methods are minimum requirements for the SensorNetAddress class. 00037 isMatch(SensorNetAddress* ) 00038 operator =(SensorNetAddress& ) 00039 setAddress(string* ) 00040 sprint(char* ) 00041 00042 UDPPort class requires these 3 methods. 00043 getIpAddress(void) 00044 getPortNo(void) 00045 setAddress(uint32_t IpAddr, uint16_t port) 00046 00047 ============================================*/ 00048 SensorNetAddress::SensorNetAddress() 00049 { 00050 _portNo = 0; 00051 _IpAddr = 0; 00052 } 00053 00054 SensorNetAddress::~SensorNetAddress() 00055 { 00056 00057 } 00058 00059 uint32_t SensorNetAddress::getIpAddress(void) 00060 { 00061 return _IpAddr; 00062 } 00063 00064 uint16_t SensorNetAddress::getPortNo(void) 00065 { 00066 return _portNo; 00067 } 00068 00069 void SensorNetAddress::setAddress(uint32_t IpAddr, uint16_t port) 00070 { 00071 _IpAddr = IpAddr; 00072 _portNo = port; 00073 } 00074 00075 /** 00076 * Set Address data to SensorNetAddress 00077 * 00078 * @param *ip_port is "IP_Address:PortNo" format string 00079 * @return success = 0, Invalid format = -1 00080 * 00081 * This function is used in ClientList::authorize(const char* fileName) 00082 * e.g. 00083 * Authorized clients are defined by fileName = "clients.conf" 00084 * 00085 * Client02,172.16.1.7:12002 00086 * Client03,172.16.1.8:13003 00087 * Client01,172.16.1.6:12001 00088 * 00089 * This definition is necessary when using TLS connection. 00090 * Gateway rejects clients not on the list for security reasons. 00091 * 00092 */ 00093 int SensorNetAddress::setAddress(string* ip_port) 00094 { 00095 size_t pos = ip_port->find_first_of(":"); 00096 00097 if ( pos == string::npos ) 00098 { 00099 _portNo = 0; 00100 _IpAddr = INADDR_NONE; 00101 return -1; 00102 } 00103 00104 string ip = ip_port->substr(0, pos); 00105 string port = ip_port->substr(pos + 1); 00106 int portNo = 0; 00107 00108 if ((portNo = atoi(port.c_str())) == 0 || (_IpAddr = inet_addr(ip.c_str())) == INADDR_NONE) 00109 { 00110 return -1; 00111 } 00112 _portNo = htons(portNo); 00113 return 0; 00114 } 00115 00116 bool SensorNetAddress::isMatch(SensorNetAddress* addr) 00117 { 00118 return ((this->_portNo == addr->_portNo) && (this->_IpAddr == addr->_IpAddr)); 00119 } 00120 00121 SensorNetAddress& SensorNetAddress::operator =(SensorNetAddress& addr) 00122 { 00123 this->_portNo = addr._portNo; 00124 this->_IpAddr = addr._IpAddr; 00125 return *this; 00126 } 00127 00128 00129 char* SensorNetAddress::sprint(char* buf) 00130 { 00131 struct in_addr inaddr = { _IpAddr }; 00132 char* ip = inet_ntoa(inaddr); 00133 sprintf( buf, "%s:", ip); 00134 sprintf( buf + strlen(buf), "%d", ntohs(_portNo)); 00135 return buf; 00136 } 00137 00138 00139 /*================================================================ 00140 Class SensorNetwork 00141 00142 In Gateway version 1.0 00143 00144 getDescpription( ) is used by Gateway::initialize( ) 00145 initialize( ) is used by ClientSendTask::initialize( ) 00146 getSenderAddress( ) is used by ClientRecvTask::run( ) 00147 broadcast( ) is used by MQTTSNPacket::broadcast( ) 00148 unicast( ) is used by MQTTSNPacket::unicast( ) 00149 read( ) is used by MQTTSNPacket::recv( ) 00150 00151 ================================================================*/ 00152 00153 SensorNetwork::SensorNetwork() 00154 { 00155 } 00156 00157 SensorNetwork::~SensorNetwork() 00158 { 00159 } 00160 00161 int SensorNetwork::unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendToAddr) 00162 { 00163 return UDPPort::unicast(payload, payloadLength, sendToAddr); 00164 } 00165 00166 int SensorNetwork::broadcast(const uint8_t* payload, uint16_t payloadLength) 00167 { 00168 return UDPPort::broadcast(payload, payloadLength); 00169 } 00170 00171 int SensorNetwork::read(uint8_t* buf, uint16_t bufLen) 00172 { 00173 return UDPPort::recv(buf, bufLen, &_clientAddr); 00174 } 00175 00176 /** 00177 * Prepare UDP sockets and description of SensorNetwork like 00178 * "UDP Multicast 225.1.1.1:1883 Gateway Port 10000". 00179 * The description is for a start up prompt. 00180 * @return success = 0, error = -1 00181 */ 00182 int SensorNetwork::initialize(void) 00183 { 00184 char param[MQTTSNGW_PARAM_MAX]; 00185 uint16_t multicastPortNo = 0; 00186 uint16_t unicastPortNo = 0; 00187 string ip; 00188 00189 /* 00190 * theProcess->getParam( ) copies 00191 * a text specified by "Key" into param[] from the Gateway.conf 00192 * 00193 * in Gateway.conf e.g. 00194 * 00195 * # UDP 00196 * GatewayPortNo=10000 00197 * MulticastIP=225.1.1.1 00198 * MulticastPortNo=1883 00199 * 00200 */ 00201 if (theProcess->getParam("MulticastIP", param) == 0) 00202 { 00203 ip = param; 00204 _description = "UDP Multicast "; 00205 _description += param; 00206 } 00207 if (theProcess->getParam("MulticastPortNo", param) == 0) 00208 { 00209 multicastPortNo = atoi(param); 00210 _description += ":"; 00211 _description += param; 00212 } 00213 if (theProcess->getParam("GatewayPortNo", param) == 0) 00214 { 00215 unicastPortNo = atoi(param); 00216 _description += " Gateway Port "; 00217 _description += param; 00218 } 00219 00220 /* Prepare UDP sockets */ 00221 return UDPPort::open(ip.c_str(), multicastPortNo, unicastPortNo); 00222 } 00223 00224 const char* SensorNetwork::getDescription(void) 00225 { 00226 return _description.c_str(); 00227 } 00228 00229 SensorNetAddress* SensorNetwork::getSenderAddress(void) 00230 { 00231 return &_clientAddr; 00232 } 00233 00234 /*========================================= 00235 Class udpStack 00236 =========================================*/ 00237 00238 UDPPort::UDPPort() 00239 { 00240 _disconReq = false; 00241 _sockfdUnicast = -1; 00242 _sockfdMulticast = -1; 00243 } 00244 00245 UDPPort::~UDPPort() 00246 { 00247 close(); 00248 } 00249 00250 void UDPPort::close(void) 00251 { 00252 if (_sockfdUnicast > 0) 00253 { 00254 ::close(_sockfdUnicast); 00255 _sockfdUnicast = -1; 00256 } 00257 if (_sockfdMulticast > 0) 00258 { 00259 ::close(_sockfdMulticast); 00260 _sockfdMulticast = -1; 00261 } 00262 } 00263 00264 int UDPPort::open(const char* ipAddress, uint16_t multiPortNo, uint16_t uniPortNo) 00265 { 00266 char loopch = 0; 00267 const int reuse = 1; 00268 00269 if (uniPortNo == 0 || multiPortNo == 0) 00270 { 00271 D_NWSTACK("error portNo undefined in UDPPort::open\n"); 00272 return -1; 00273 } 00274 00275 uint32_t ip = inet_addr(ipAddress); 00276 _grpAddr.setAddress(ip, htons(multiPortNo)); 00277 _clientAddr.setAddress(ip, htons(uniPortNo)); 00278 00279 /*------ Create unicast socket --------*/ 00280 _sockfdUnicast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 00281 if (_sockfdUnicast < 0) 00282 { 00283 D_NWSTACK("error can't create unicast socket in UDPPort::open\n"); 00284 return -1; 00285 } 00286 00287 setsockopt(_sockfdUnicast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); 00288 00289 sockaddr_in addru; 00290 addru.sin_family = AF_INET; 00291 addru.sin_port = htons(uniPortNo); 00292 addru.sin_addr.s_addr = INADDR_ANY; 00293 00294 if (::bind(_sockfdUnicast, (sockaddr*) &addru, sizeof(addru)) < 0) 00295 { 00296 D_NWSTACK("error can't bind unicast socket in UDPPort::open\n"); 00297 return -1; 00298 } 00299 if (setsockopt(_sockfdUnicast, IPPROTO_IP, IP_MULTICAST_LOOP, (char*) &loopch, sizeof(loopch)) < 0) 00300 { 00301 D_NWSTACK("error IP_MULTICAST_LOOP in UDPPort::open\n"); 00302 close(); 00303 return -1; 00304 } 00305 00306 /*------ Create Multicast socket --------*/ 00307 _sockfdMulticast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 00308 if (_sockfdMulticast < 0) 00309 { 00310 D_NWSTACK("error can't create multicast socket in UDPPort::open\n"); 00311 close(); 00312 return -1; 00313 } 00314 00315 setsockopt(_sockfdMulticast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); 00316 00317 sockaddr_in addrm; 00318 addrm.sin_family = AF_INET; 00319 addrm.sin_port = _grpAddr.getPortNo(); 00320 addrm.sin_addr.s_addr = INADDR_ANY; 00321 00322 if (::bind(_sockfdMulticast, (sockaddr*) &addrm, sizeof(addrm)) < 0) 00323 { 00324 D_NWSTACK("error can't bind multicast socket in UDPPort::open\n"); 00325 return -1; 00326 } 00327 if (setsockopt(_sockfdMulticast, IPPROTO_IP, IP_MULTICAST_LOOP, (char*) &loopch, sizeof(loopch)) < 0) 00328 { 00329 D_NWSTACK("error IP_MULTICAST_LOOP in UDPPort::open\n"); 00330 close(); 00331 return -1; 00332 } 00333 00334 ip_mreq mreq; 00335 mreq.imr_interface.s_addr = INADDR_ANY; 00336 mreq.imr_multiaddr.s_addr = _grpAddr.getIpAddress(); 00337 00338 if (setsockopt(_sockfdMulticast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) 00339 { 00340 D_NWSTACK("error Multicast IP_ADD_MEMBERSHIP in UDPPort::open\n"); 00341 close(); 00342 return -1; 00343 } 00344 00345 if (setsockopt(_sockfdUnicast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) 00346 { 00347 D_NWSTACK("error Unicast IP_ADD_MEMBERSHIP in UDPPort::open\n"); 00348 close(); 00349 return -1; 00350 } 00351 return 0; 00352 } 00353 00354 int UDPPort::unicast(const uint8_t* buf, uint32_t length, SensorNetAddress* addr) 00355 { 00356 sockaddr_in dest; 00357 dest.sin_family = AF_INET; 00358 dest.sin_port = addr->getPortNo(); 00359 dest.sin_addr.s_addr = addr->getIpAddress(); 00360 00361 int status = ::sendto(_sockfdUnicast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest)); 00362 if (status < 0) 00363 { 00364 D_NWSTACK("errno == %d in UDPPort::sendto\n", errno); 00365 } 00366 D_NWSTACK("sendto %s:%u length = %d\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), status); 00367 return status; 00368 } 00369 00370 int UDPPort::broadcast(const uint8_t* buf, uint32_t length) 00371 { 00372 return unicast(buf, length, &_grpAddr); 00373 } 00374 00375 int UDPPort::recv(uint8_t* buf, uint16_t len, SensorNetAddress* addr) 00376 { 00377 struct timeval timeout; 00378 fd_set recvfds; 00379 int maxSock = 0; 00380 00381 timeout.tv_sec = 0; 00382 timeout.tv_usec = 1000000; // 1 sec 00383 FD_ZERO(&recvfds); 00384 FD_SET(_sockfdUnicast, &recvfds); 00385 FD_SET(_sockfdMulticast, &recvfds); 00386 00387 if (_sockfdMulticast > _sockfdUnicast) 00388 { 00389 maxSock = _sockfdMulticast; 00390 } 00391 else 00392 { 00393 maxSock = _sockfdUnicast; 00394 } 00395 00396 int rc = 0; 00397 if ( select(maxSock + 1, &recvfds, 0, 0, &timeout) > 0 ) 00398 { 00399 if (FD_ISSET(_sockfdUnicast, &recvfds)) 00400 { 00401 rc = recvfrom(_sockfdUnicast, buf, len, 0, addr); 00402 } 00403 else if (FD_ISSET(_sockfdMulticast, &recvfds)) 00404 { 00405 rc = recvfrom(_sockfdMulticast, buf, len, 0, &_grpAddr); 00406 } 00407 } 00408 return rc; 00409 } 00410 00411 int UDPPort::recvfrom(int sockfd, uint8_t* buf, uint16_t len, uint8_t flags, SensorNetAddress* addr) 00412 { 00413 sockaddr_in sender; 00414 socklen_t addrlen = sizeof(sender); 00415 memset(&sender, 0, addrlen); 00416 00417 int status = ::recvfrom(sockfd, buf, len, flags, (sockaddr*) &sender, &addrlen); 00418 00419 if (status < 0 && errno != EAGAIN) 00420 { 00421 D_NWSTACK("errno == %d in UDPPort::recvfrom\n", errno); 00422 return -1; 00423 } 00424 addr->setAddress(sender.sin_addr.s_addr, sender.sin_port); 00425 D_NWSTACK("recved from %s:%d length = %d\n", inet_ntoa(sender.sin_addr),ntohs(sender.sin_port), status); 00426 return status; 00427 } 00428
Generated on Wed Jul 13 2022 10:46:03 by
1.7.2