Main MRPT website > C++ reference for MRPT 1.9.9
CServerTCPSocket_common.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "comms-precomp.h" // Precompiled headers
11 
14 #include <mrpt/comms/net_utils.h>
15 #include <mrpt/system/os.h>
16 #include <mrpt/core/exceptions.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 <sys/socket.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <errno.h>
27 #include <sys/types.h>
28 #include <sys/ioctl.h>
29 #include <netdb.h>
30 #include <arpa/inet.h>
31 #include <netinet/in.h>
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  format(
74  "[CServerTCPSocket] Listening at %s:%i\n", IPaddress.c_str(),
75  listenPort));
76 
77  MRPT_END
78 }
79 
80 /*---------------------------------------------------------------
81  isListening
82  ---------------------------------------------------------------*/
83 bool CServerTCPSocket::isListening() { return INVALID_SOCKET != m_serverSock; }
84 /*---------------------------------------------------------------
85  accept
86  ---------------------------------------------------------------*/
87 std::unique_ptr<CClientTCPSocket> CServerTCPSocket::accept(int timeout_ms)
88 {
90 
91  if (m_serverSock == INVALID_SOCKET) return nullptr;
92 
93  struct timeval timeoutSelect;
94  struct timeval* ptrTimeout;
95  fd_set sockArr;
96 
97  // Init fd_set structure & add our socket to it:
98  FD_ZERO(&sockArr);
99  FD_SET(m_serverSock, &sockArr);
100 
101  // The timeout:
102  if (timeout_ms < 0)
103  {
104  ptrTimeout = nullptr;
105  }
106  else
107  {
108  timeoutSelect.tv_sec = timeout_ms / 1000;
109  timeoutSelect.tv_usec = 1000 * (timeout_ms % 1000);
110  ptrTimeout = &timeoutSelect;
111  }
112 
113  // Wait for READ flag (meaning incoming connections):
114  MRPT_LOG_DEBUG("[CServerTCPSocket::accept] Waiting incoming connections");
115 
116  int selRet = ::select(
117  m_serverSock + 1, // __nfds
118  &sockArr, // Wait for read
119  nullptr, // Wait for write
120  nullptr, // Wait for except.
121  ptrTimeout); // Timeout
122 
123  if (selRet == INVALID_SOCKET)
124  {
125  fprintf(stderr, "%s\n", getLastErrorStr().c_str());
126  return nullptr;
127  }
128 
129  if (selRet == 0)
130  {
132  "[CServerTCPSocket::accept] Timeout waiting incoming "
133  "connections\n");
134 
135  // Timeout:
136  return nullptr;
137  }
138  else
139  {
141  "[CServerTCPSocket::accept] Incoming connection accepted\n");
142 
143  // We have a new connection:
144 
145  sockaddr_in otherPart;
146  socklen_t otherPartSize = sizeof(otherPart);
147 
148  int aceptdSock = ::accept(
149  m_serverSock, (struct sockaddr*)&otherPart, &otherPartSize);
150 
151  if (aceptdSock == INVALID_SOCKET)
152  {
153  MRPT_LOG_ERROR_FMT("%s\n", getLastErrorStr().c_str());
154  return std::unique_ptr<CClientTCPSocket>();
155  }
156 
157  auto ret = std::make_unique<CClientTCPSocket>();
158 
159  ret->m_hSock = aceptdSock;
160 
161  ret->m_remotePartIP = std::string(inet_ntoa(otherPart.sin_addr));
162  ret->m_remotePartPort = ntohs(otherPart.sin_port);
163 
165  "[CServerTCPSocket::accept] Connection accepted from %s:%u\n",
166  ret->m_remotePartIP.c_str(), ret->m_remotePartPort);
167 
168  return ret;
169  }
170 
171  MRPT_END
172 }
#define MRPT_START
Definition: exceptions.h:262
#define MRPT_LOG_DEBUG(_STRING)
Use: MRPT_LOG_DEBUG("message");
#define MRPT_LOG_ERROR_FMT(_FMT_STRING,...)
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
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);
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
GLsizei const GLchar ** string
Definition: glext.h:4101
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
Definition: os.cpp:406
#define MRPT_END
Definition: exceptions.h:266
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 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at lun oct 28 00:14:14 CET 2019