tobicore  7.0.0
 All Classes Functions Variables Typedefs Enumerator Friends Groups Pages
TPSocket.cpp
1 /*
2  Copyright (C) 2009-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
3  Michele Tavella <michele.tavella@epfl.ch>
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  TPSocket.hpp/.cpp is adapted from libtransport
19 */
20 
21 #ifndef TPSOCKET_CPP
22 #define TPSOCKET_CPP
23 
24 #include "TPSocket.hpp"
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #ifdef _WIN32
30 #include <stdio.h>
31 #endif
32 
34  memset(this->address, 0, TPHost::AddressSize);
35  this->port = 0;
36 }
37 
38 #ifdef _WIN32
39 bool TPSocket::_wsaInitialized = false;
40 #endif
41 
42 TPSocket::TPSocket(int type, size_t bsize) {
43  this->_type = type;
44  this->_bsize = bsize;
45  this->_mc = 256;
46  this->_buffer = NULL;
47  this->_fd = -1;
48 }
49 
51 }
52 
53 bool TPSocket::Async(bool block) {
54 #ifndef __MINGW32__
55  int oldflags = fcntl(this->_fd, F_GETFL, 0);
56  if(oldflags < 0)
57  return false;
58 
59  if(block == true)
60  oldflags |= O_NONBLOCK;
61  else
62  oldflags &= ~O_NONBLOCK;
63  return(fcntl(this->_fd, F_SETFL, oldflags) > -1);
64 #else
65  u_long arg = (u_long)block;
66  ioctlsocket(this->_fd, FIONBIO, &arg);
67  return true;
68 #endif
69 }
70 
71 void TPSocket::Init(void) {
72  this->_fd = 0;
73  this->_mc = 0;
74  this->_bsizemax = 0;
75 
76  this->Free();
77  this->_buffer = malloc(this->_bsize);
78  memset(this->_buffer, 0, this->_bsize);
79 
80  memset(&(this->_address), 0, sizeof(this->_address));
81  memset(&(this->_results), 0, sizeof(this->_results));
82  memset(&(this->_endpoint), 0, sizeof(this->_endpoint));
83 
84  this->_bsizemax = 0;
85 #ifdef _WIN32
86  /* Stays here for the time being, later on I will handle
87  * the (doggie)initialization better.
88  */
89  TPSocket::InitializeWSA();
90 #endif
91 }
92 
93 void TPSocket::Free(void) {
94  if(this->_buffer == NULL)
95  return;
96  free(this->_buffer);
97  this->_buffer = NULL;
98 }
99 
100 bool TPSocket::GetLocal(void) {
101 #ifndef _WIN32
102  const char* status = NULL;
103  struct sockaddr addr;
104  int addrlen = sizeof(addr);
105 
106  getsockname(this->_fd,
107  (struct sockaddr*)&addr, (socklen_t*)&addrlen);
108  struct sockaddr_in *addr_ptr = (struct sockaddr_in*)&addr;
109 
110  this->local.port = ntohs(addr_ptr->sin_port);
111  status = inet_ntop(AF_INET,
112  &(addr_ptr->sin_addr.s_addr), this->local.address,
113  (socklen_t)addrlen);
114  return(status != NULL);
115 #else
116  return false;
117 #endif
118 }
119 
121 #ifndef _WIN32
122  const char* status = NULL;
123  struct sockaddr addr;
124  int addrlen = sizeof(addr);
125 
126  getpeername(this->_fd,
127  (struct sockaddr*)&addr, (socklen_t*)&addrlen);
128  struct sockaddr_in *addr_ptr = (struct sockaddr_in*)&addr;
129 
130  this->remote.port = ntohs(addr_ptr->sin_port);
131  status = inet_ntop(AF_INET, &(addr_ptr->sin_addr.s_addr),
132  this->remote.address, (socklen_t)addrlen);
133  return(status != NULL);
134 #else
135  return false;
136 #endif
137 }
138 
140  socklen_t optlen = sizeof(this->_bsizemax);
141 #ifndef _WIN32
142  if(getsockopt(this->_fd, SOL_SOCKET, SO_SNDBUF, &this->_bsizemax,
143  &optlen) < 0)
144  this->_bsizemax = 0;
145 #else
146  this->_bsizemax = 0;
147 #endif
148 }
149 
150 bool TPSocket::Open(bool asserver) {
151  switch(this->_type) {
152  case TPSocket::TCP:
153  this->_results.ai_socktype = SOCK_STREAM;
154  break;
155  case TPSocket::UDP:
156  this->_results.ai_socktype = SOCK_DGRAM;
157  break;
158  default:
159  return false;
160  }
161  if(asserver == true)
162  this->_results.ai_flags = AI_PASSIVE;
163  this->_results.ai_family = AF_UNSPEC;
164 
165  this->Init();
166  return true;
167 }
168 
169 bool TPSocket::Close(void) {
170  return(close(this->_fd) == 0);
171 }
172 
173 bool TPSocket::Bind(const std::string& ip, const std::string& port) {
174  int retopt = 0;
175  int bndret = 0;
176  struct addrinfo *ai;
177  int opt = 1;
178 
179  if(getaddrinfo(ip.c_str(), port.c_str(), &(this->_results), &ai) != 0)
180  return -1;
181 
182  for(this->_info = ai; this->_info != NULL;
183  this->_info = this->_info->ai_next) {
184  this->_fd = socket(this->_info->ai_family,
185  this->_info->ai_socktype,
186  this->_info->ai_protocol);
187  if(this->_fd == -1)
188  continue;
189 
190 #ifndef _WIN32
191  if(this->_type == TPSocket::TCP) {
192  retopt = setsockopt(this->_fd,
193  SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
194  if(retopt == -1)
195  return false;
196  }
197 #endif
198  bndret = bind(this->_fd, this->_info->ai_addr, this->_info->ai_addrlen);
199  if(bndret == -1) {
200  close(this->_fd);
201  continue;
202  }
203  break;
204  }
205  freeaddrinfo(ai);
206 
207  this->GetLocal();
208 
209  return(bndret == 0);
210 }
211 
212 bool TPSocket::Listen(void) {
213  return(listen(this->_fd, this->_mc) == 0);
214 }
215 
216 int TPSocket::Accept(TPSocket* endpoint) {
217  if(endpoint->_type != this->_type)
218  return -3;
219  endpoint->Init();
220 
221  unsigned int addrlen = sizeof(endpoint->_address);
222 
223  /*
224  endpoint->_fd = accept(this->_fd, (struct sockaddr*)&this->_endpoint,
225  &addrlen);
226  */
227  endpoint->_fd = accept(this->_fd, (struct sockaddr*)&this->_endpoint,
228  (socklen_t*)&addrlen);
229 
230  this->GetLocal();
231  this->GetRemote();
232  return endpoint->_fd;
233 }
234 
235 bool TPSocket::Connect(const std::string& ip, const std::string& port) {
236  struct addrinfo *ai;
237  int conopt = 0;
238 
239  if(getaddrinfo(ip.c_str(), port.c_str(), &(this->_results), &ai) != 0)
240  return false;
241 
242  for(this->_info = ai; this->_info != NULL; this->_info = this->_info->ai_next) {
243  this->_fd = socket(this->_info->ai_family,
244  this->_info->ai_socktype, this->_info->ai_protocol);
245  if(this->_fd == -1)
246  continue;
247 
248  if(this->_type == TPSocket::TCP) {
249  conopt = connect(this->_fd, this->_info->ai_addr,
250  this->_info->ai_addrlen);
251  if(conopt == -1) {
252  this->Close();
253  continue;
254  }
255  }
256  break;
257  }
258 
259  this->GetMaxBSize();
260  this->GetLocal();
261  this->GetRemote();
262 
263  return(conopt == 0);
264 }
265 
266 ssize_t TPSocket::Send(const std::string& message) {
267  ssize_t bytes = -1;
268  switch(this->_type) {
269  case TPSocket::TCP:
270 #ifndef _WIN32
271  bytes = send(this->_fd, message.c_str(), message.size(),
272  MSG_NOSIGNAL);
273 #else
274  bytes = send(this->_fd, message.c_str(), message.size(), 0);
275 #endif
276  break;
277  case TPSocket::UDP:
278  return sendto(this->_fd, message.c_str(), message.size(), 0,
279  this->_info->ai_addr, this->_info->ai_addrlen);
280  break;
281  }
282  return bytes;
283 }
284 
285 ssize_t TPSocket::Recv(std::string* message) {
286  ssize_t bytes = -1;
287  switch(this->_type) {
288  case TPSocket::TCP:
289 #ifndef _WIN32
290  bytes = recv(this->_fd, this->_buffer, this->_bsize, 0);
291 #else
292  bytes = recv(this->_fd, (char*)this->_buffer, this->_bsize, 0);
293 #endif
294  break;
295  case TPSocket::UDP:
296  int addr_len = sizeof(this->_endpoint);
297 #ifndef _WIN32
298  bytes = recvfrom(this->_fd, this->_buffer, this->_bsize, 0,
299  (struct sockaddr *)&this->_endpoint, (socklen_t*)&addr_len);
300 #else
301  bytes = recvfrom(this->_fd, (char*)this->_buffer, this->_bsize, 0,
302  (struct sockaddr *)&this->_endpoint, (socklen_t*)&addr_len);
303 #endif
304  break;
305  }
306 
307  if(bytes > 0)
308  message->assign((const char*)this->_buffer, (size_t)bytes);
309 
310  return bytes;
311 }
312 
313 #ifdef _WIN32
314 bool TPSocket::InitializeWSA(void) {
315  if(TPSocket::_wsaInitialized == true)
316  return true;
317 
318  WSADATA wsaData;
319  TPSocket::_wsaInitialized = (WSAStartup(MAKEWORD(2,2), &wsaData) != 0);
320  return TPSocket::_wsaInitialized;
321 }
322 #endif
323 
325  std::string empty;
326  empty.push_back('\0');
327  return(this->Send(empty) > (ssize_t)0);
328 }
329 
330 #endif