Jack Hansdampf / mbed-mqtt-GSOE1

Dependents:   ESP8266MQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SensorNetwork.cpp Source File

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