blob: c645b52b1d53d77dce5a43637f2edc780a1b4545 [file] [log] [blame]
Vadim Ioseviche76832c2017-11-05 09:09:14 +02001/*
2 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#ifdef __linux
31#include <stdlib.h>
32#include <string.h>
33#include <cerrno>
34#include <unistd.h>
35#include <netinet/in.h>
36#include <sys/socket.h>
37#include <arpa/inet.h>
38#include <net/if.h>
39#include <netinet/in.h>
40#include <sys/ioctl.h>
41#include <sys/types.h>
42#include <dirent.h>
43#include <stdio.h>
44
45#elif _WINDOWS
46#include <windows.h>
47
48#else
49#include <dirent.h>
50#include <sys/socket.h>
51#include <net/route.h>
52#include <net/if.h>
53#include <arpa/inet.h>
54#endif
55
56#include <iostream>
57#include <fstream>
58#include <sstream>
59#include "DebugLogger.h"
60#include "UdpNetworkInterface.h"
61
62UdpNetworkInterface::UdpNetworkInterface(std::string broadcastIp, int portIn, int portOut)
63{
64 m_portIn = portIn;
65 m_portOut = portOut;
66 m_broadcastIp = broadcastIp;
67#ifndef _WINDOWS
68 // create UDP socket
69 m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
70 if (m_socket < 0)
71 {
72 std::string error = "Can't open UDP socket";
73 LOG_WARNING << error << std::endl;
74 throw error;
75 }
76
77 // set broadcast flag on
78 int enabled = 1;
79 if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (char*)&enabled, sizeof(enabled)) < 0)
80 {
81 std::string error = "Can't set broadcast option for udp socket, error: ";
82 error += strerror(errno);
83
84 LOG_WARNING << error << std::endl;
85 shutdown(m_socket, SHUT_RDWR);
86 throw error;
87 }
88
89 // bind socket to portIn
90 struct sockaddr_in address;
91 address.sin_family = AF_INET;
92 address.sin_addr.s_addr = INADDR_ANY;
93 address.sin_port = htons(m_portIn);
94 if (::bind(m_socket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0)
95 {
96 std::string error = "Can't bind socket to port, error: ";
97 error += strerror(errno);
98
99 LOG_WARNING << error << std::endl;
100 throw error;
101 }
102#else
103 std::string error = "UDP socket is supported on linux OS only";
104 throw error;
105#endif
106}
107
108int UdpNetworkInterface::Send(std::string message)
109{
110#ifndef _WINDOWS
111 struct sockaddr_in dstAddress;
112 dstAddress.sin_family = AF_INET;
113 inet_pton(AF_INET, m_broadcastIp.c_str(), &dstAddress.sin_addr.s_addr);
114 dstAddress.sin_port = htons(m_portOut);
115 int messageSize = message.length() * sizeof(char);
116 int result = sendto(m_socket, message.c_str(), messageSize, 0, (sockaddr*)&dstAddress, sizeof(dstAddress));
117 LOG_VERBOSE << "INFO : sendto with sock_out=" << m_socket << ", message=" << message << " messageSize=" << messageSize << " returned with " << result << std::endl;
118 if (result < 0)
119 {
120 LOG_WARNING << "ERROR : Cannot send udp broadcast message, error " << ": " << strerror(errno) << std::endl;
121 return 0;
122 }
123 return messageSize;
124#else
125 return 0;
126#endif
127}
128
129const char* UdpNetworkInterface::Receive(int len)
130{
131#ifndef _WINDOWS
132 char* buf = new char[len];
Vadim Iosevich82902242018-02-13 14:07:05 +0200133 if (nullptr == buf)
134 {
135 LOG_ERROR << "Cannot allocate receive buffer for UDP messages" << std::endl;
136 return "";
137 }
138
Vadim Ioseviche76832c2017-11-05 09:09:14 +0200139 if (recvfrom(m_socket, buf, len, 0, NULL, 0) < 0)
140 {
141 LOG_WARNING << "Can't receive from port " << m_portIn << std::endl;
142 return "";
143 }
144 return buf;
145#else
146 return "";
147#endif
148}
149
150void UdpNetworkInterface::Close()
151{
152#ifndef _WINDOWS
153 shutdown(m_socket, SHUT_RDWR);
154#endif
155}