]> git.vomp.tv Git - vompclient.git/blob - udp4.cc
Fix VRecording showing graphic at bottom left when it shouldn't
[vompclient.git] / udp4.cc
1 /*
2     Copyright 2004-2020 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #ifndef WIN32
21 #include <netdb.h>
22 #include <unistd.h>
23 #include <arpa/inet.h>
24 #include <sys/time.h>
25 #define SOCKET_ERROR 0
26 #else
27 #include <winsock2.h>
28 #include <Ws2tcpip.h>
29 #include <sys/timeb.h>
30 #endif
31
32 #include <sys/types.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37
38 #include "defines.h"
39 #include "log.h"
40
41 #include "udp4.h"
42
43 static const char* TAG = "UDP4";
44
45 UDP4::~UDP4()
46 {
47   if (initted) shutdown();
48 }
49
50 int UDP4::init(USHORT tport)
51 {
52   if (initted) return 0;
53   
54   myPort = tport;
55   addrlen = sizeof(struct sockaddr);
56
57   if ((socketnum = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
58   { perror("socket"); return 0; }
59
60   myAddr.sin_family = AF_INET;         // host byte order
61   myAddr.sin_port = htons(myPort);     // short, network byte order
62   myAddr.sin_addr.s_addr = getIPNumber(iterate_ip++); // auto-fill with my IP
63   memset(&(myAddr.sin_zero), 0, 8);    // zero the rest of the struct
64
65   if (bind(socketnum, reinterpret_cast<struct sockaddr *>(&myAddr), addrlen) == -1)
66   { perror("bind"); return 0; }
67
68   FD_ZERO(&readfds);
69   FD_SET(socketnum, &readfds);
70   tv.tv_sec = 0;
71   tv.tv_usec = 0;
72
73   int allowed = 1;
74
75 #ifdef WIN32
76   setsockopt(socketnum, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&allowed), sizeof(allowed));
77 #else
78   setsockopt(socketnum, SOL_SOCKET, SO_BROADCAST, static_cast<void*>(&allowed), sizeof(allowed));
79 #endif
80
81   initted = true;
82
83   return 1;
84 }
85
86 void UDP4::shutdown()
87 {
88   if (!initted) return;
89   CLOSESOCKET(socketnum);
90   initted = false;
91 }
92
93 #ifdef WIN32
94 unsigned char UDP4::waitforMessage(unsigned char how, SOCKET quitPipe)
95 #else
96 unsigned char UDP4::waitforMessage(unsigned char how, int quitPipe)
97 #endif
98 {
99   if (!initted) return 0;
100
101   /* how = 0 - block
102      how = 1 - start new wait
103      how = 2 - continue wait
104      how = 3 - block, return on byte from quitPipe
105   */
106
107   FD_ZERO(&readfds);
108   FD_SET(socketnum, &readfds);
109
110   struct timeval* passToSelect = NULL;
111
112   int sockMaxP1 = socketnum + 1;
113
114   if (how == 1)
115   {
116     tv.tv_sec = 1;
117     tv.tv_usec = 500000;
118     passToSelect = &tv;
119   }
120   else if (how == 2)
121   {
122     if ((tv.tv_sec == 0) && (tv.tv_usec == 0))  // protection in case timer = 0
123     {
124       tv.tv_sec = 1;
125       tv.tv_usec = 500000;
126     }
127     passToSelect = &tv;
128   }
129   else if (how == 3)
130   {
131     FD_SET(quitPipe, &readfds);
132     if (quitPipe > socketnum) sockMaxP1 = quitPipe + 1;
133   }
134
135
136   if (select(sockMaxP1, &readfds, NULL, NULL, passToSelect) <= 0)
137   {  return 1;  }
138
139   if ((how == 3) && FD_ISSET(quitPipe, &readfds)) return 3;
140
141   if ((mlength = recvfrom(socketnum, buf, MAXBUFLEN, 0,
142       reinterpret_cast<struct sockaddr *>(&theirAddr), &addrlen)) == -1)
143   { perror("recvfrom"); return 0; }
144   else
145   {
146     memset(&buf[mlength], 0, MAXBUFLEN - mlength);
147     strcpy(fromIPA, inet_ntoa(theirAddr.sin_addr));
148     fromPort = ntohs(theirAddr.sin_port);
149
150     return 2;
151   }
152
153   /* Return 0, failure
154      Return 1, nothing happened, timer expired
155      Return 2, packet arrived (timer not expired)
156   */
157 }
158
159 UINT UDP4::getDataLength(void) const
160 {
161   return static_cast<UINT>(mlength);
162 }
163
164 const void* UDP4::getData() const     {  return buf;  }
165 const char* UDP4::getFromIPA() const  {  return fromIPA;  }
166 short UDP4::getFromPort() const       {  return fromPort; }
167
168 bool UDP4::send(const char *ipa, USHORT port, char *message, int length)
169 {
170   if (!initted) return false;
171
172   int sentLength = 0;
173
174   struct sockaddr_in sendAddr;
175   sendAddr.sin_family = AF_INET;      // host byte order
176   sendAddr.sin_port = htons(port);    // short, network byte order
177   struct in_addr tad;                 // temp struct tad needed to pass to sendAddr.sin_addr
178   tad.s_addr = inet_addr(ipa);
179   sendAddr.sin_addr = tad;            // address
180   memset(&(sendAddr.sin_zero), 0, 8); // zero the rest of the struct
181
182   errno = 0;
183
184   sentLength = sendto(socketnum, message, length, 0, reinterpret_cast<struct sockaddr *>(&sendAddr), addrlen);
185   if (sentLength == length) return true;
186   LogNT::getInstance()->error(TAG, "sendto failed, errno = {}", errno);
187   return false;
188 }
189
190 #ifndef WIN32
191 ULONG UDP4::getIPNumber(ULONG)
192 {
193   return INADDR_ANY;
194 }
195 #else
196 ULONG UDP4::getIPNumber(ULONG num)
197 {
198   char buffer[100];
199   ULONG returnaddress;
200
201   if (gethostname(buffer,sizeof(buffer))==SOCKET_ERROR)
202   {
203     return INADDR_ANY; //well take any address, if we fail
204   }
205
206   struct hostent *hosts=gethostbyname(buffer);
207   if (hosts==NULL)
208   {
209     return INADDR_ANY; //well take any address, if we fail
210   }
211
212   int num_ip=0;
213   for (num_ip=0;hosts->h_addr_list[num_ip]!=NULL;num_ip++);
214
215   int get_ip=(num%num_ip);//Just wrap around, if no interface are present any more
216   memcpy(&returnaddress, hosts->h_addr_list[get_ip], sizeof(ULONG));
217   return returnaddress;
218 }
219 #endif