MRPT  2.0.2
CServerTCPSocket_common.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "comms-precomp.h" // Precompiled headers
11 
14 #include <mrpt/comms/net_utils.h>
15 #include <mrpt/core/exceptions.h>
16 #include <mrpt/system/os.h>
17 #include <cstdio> // stderr
18 using namespace mrpt::comms;
19 
20 #if defined(MRPT_OS_LINUX) || defined(__APPLE__)
21 #define INVALID_SOCKET (-1)
22 
23 #include <arpa/inet.h>
24 #include <fcntl.h>
25 #include <netdb.h>
26 #include <netinet/in.h>
27 #include <sys/ioctl.h>
28 #include <sys/socket.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31 #include <cerrno>
32 #endif
33 
34 #ifdef _WIN32
35 #include <winsock.h>
36 using socklen_t = int;
37 #endif
38 
40 {
42 }
43 
45  unsigned short listenPort, const std::string& IPaddress,
46  int maxConnectionsWaiting)
47 {
49 
50  // Create the socket:
51  // ----------------------------
52  m_serverSock = socket(AF_INET, SOCK_STREAM, 0);
53  if (INVALID_SOCKET == m_serverSock) THROW_EXCEPTION(getLastErrorStr());
54 
55  // Bind it:
56  // ----------------------------
57  sockaddr_in desiredIP;
58 
59  desiredIP.sin_family = AF_INET;
60  desiredIP.sin_addr.s_addr = inet_addr(IPaddress.c_str());
61  desiredIP.sin_port = htons((unsigned short)listenPort);
62 
63  if (INVALID_SOCKET ==
64  ::bind(m_serverSock, (struct sockaddr*)(&desiredIP), sizeof(desiredIP)))
66 
67  // Put in listen mode:
68  // ----------------------------
69  if (INVALID_SOCKET == listen(m_serverSock, maxConnectionsWaiting))
71 
73  "[CServerTCPSocket] Listening at %s:%i\n", IPaddress.c_str(),
74  listenPort));
75 
76  MRPT_END
77 }
78 
79 /*---------------------------------------------------------------
80  isListening
81  ---------------------------------------------------------------*/
82 bool CServerTCPSocket::isListening() { return INVALID_SOCKET != m_serverSock; }
83 /*---------------------------------------------------------------
84  accept
85  ---------------------------------------------------------------*/
86 std::unique_ptr<CClientTCPSocket> CServerTCPSocket::accept(int timeout_ms)
87 {
89 
90  if (m_serverSock == INVALID_SOCKET) return nullptr;
91 
92  struct timeval timeoutSelect;
93  struct timeval* ptrTimeout;
94  fd_set sockArr;
95 
96  // Init fd_set structure & add our socket to it:
97  FD_ZERO(&sockArr);
98  FD_SET(m_serverSock, &sockArr);
99 
100  // The timeout:
101  if (timeout_ms < 0)
102  {
103  ptrTimeout = nullptr;
104  }
105  else
106  {
107  timeoutSelect.tv_sec = timeout_ms / 1000;
108  timeoutSelect.tv_usec = 1000 * (timeout_ms % 1000);
109  ptrTimeout = &timeoutSelect;
110  }
111 
112  // Wait for READ flag (meaning incoming connections):
113  MRPT_LOG_DEBUG("[CServerTCPSocket::accept] Waiting incoming connections");
114 
115  int selRet = ::select(
116  m_serverSock + 1, // __nfds
117  &sockArr, // Wait for read
118  nullptr, // Wait for write
119  nullptr, // Wait for except.
120  ptrTimeout); // Timeout
121 
122  if (selRet == INVALID_SOCKET)
123  {
124  fprintf(stderr, "%s\n", getLastErrorStr().c_str());
125  return nullptr;
126  }
127 
128  if (selRet == 0)
129  {
131  "[CServerTCPSocket::accept] Timeout waiting incoming "
132  "connections\n");
133 
134  // Timeout:
135  return nullptr;
136  }
137  else
138  {
140  "[CServerTCPSocket::accept] Incoming connection accepted\n");
141 
142  // We have a new connection:
143 
144  sockaddr_in otherPart;
145  socklen_t otherPartSize = sizeof(otherPart);
146 
147  int aceptdSock = ::accept(
148  m_serverSock, (struct sockaddr*)&otherPart, &otherPartSize);
149 
150  if (aceptdSock == INVALID_SOCKET)
151  {
152  MRPT_LOG_ERROR_FMT("%s\n", getLastErrorStr().c_str());
153  return std::unique_ptr<CClientTCPSocket>();
154  }
155 
156  auto ret = std::make_unique<CClientTCPSocket>();
157 
158  ret->m_hSock = aceptdSock;
159 
160  ret->m_remotePartIP = std::string(inet_ntoa(otherPart.sin_addr));
161  ret->m_remotePartPort = ntohs(otherPart.sin_port);
162 
164  "[CServerTCPSocket::accept] Connection accepted from %s:%u\n",
165  ret->m_remotePartIP.c_str(), ret->m_remotePartPort);
166 
167  return ret;
168  }
169 
170  MRPT_END
171 }
#define MRPT_START
Definition: exceptions.h:241
#define MRPT_LOG_DEBUG(_STRING)
Use: MRPT_LOG_DEBUG("message");
#define MRPT_LOG_ERROR_FMT(_FMT_STRING,...)
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
std::string std::string format(std::string_view fmt, ARGS &&... args)
Definition: format.h:26
std::string getLastSocketErrorStr()
Returns a description of the last Sockets error.
Definition: net_utils.cpp:480
std::string getLastErrorStr()
Returns a description of the last Sockets error.
unsigned int m_serverSock
The handle for the listening server TCP socket.
std::unique_ptr< CClientTCPSocket > accept(int timeout_ms=-1)
Waits for an incoming connection (indefinitely, or with a given timeout) The returned object represen...
void setupSocket(unsigned short listenPort, const std::string &IPaddress, int maxConnectionsWaiting)
Common code called from the platform-dependant constructor.
#define MRPT_LOG_DEBUG_FMT(_FMT_STRING,...)
Use: MRPT_LOG_DEBUG_FMT("i=%u", i);
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
Definition: os.cpp:408
#define MRPT_END
Definition: exceptions.h:245
bool isListening()
Returns true if the socket was successfully open and it&#39;s bound to the desired port.
#define MRPT_LOG_WARN(_STRING)
Serial and networking devices and utilities.



Page generated by Doxygen 1.8.14 for MRPT 2.0.2 Git: 9b4fd2465 Mon May 4 16:59:08 2020 +0200 at lun may 4 17:26:07 CEST 2020