1919
2020#ifdef JERRY_DEBUGGER
2121
22- #include <arpa/inet.h>
2322#include <errno.h>
23+
24+ #ifdef WIN32
25+ #include <BaseTsd.h>
26+ typedef SSIZE_T ssize_t ;
27+ #include <WS2tcpip.h>
28+ #include <winsock2.h>
29+
30+ /* On Windows the WSAEWOULDBLOCK value can be returned for non-blocking operations */
31+ #define JERRYX_EWOULDBLOCK WSAEWOULDBLOCK
32+
33+ /* On Windows the invalid socket's value of INVALID_SOCKET */
34+ #define JERRYX_SOCKET_INVALID INVALID_SOCKET
35+
36+ /* On Windows sockets have a SOCKET typedef */
37+ typedef SOCKET jerryx_socket ;
38+
39+ #else /* !WIN32 */
40+
41+ #include <arpa/inet.h>
2442#include <fcntl.h>
25- #include <unistd.h>
2643#include <sys/socket.h>
44+ #include <unistd.h>
45+
46+ /* On *nix the EWOULDBLOCK errno value can be returned for non-blocking operations */
47+ #define JERRYX_EWOULDBLOCK EWOULDBLOCK
48+
49+ /* On *nix the invalid socket has a value of -1 */
50+ #define JERRYX_SOCKET_INVALID (-1)
51+
52+ /* On *nix the sockets are integer identifiers */
53+ typedef int jerryx_socket ;
54+ #endif /* WIN32 */
2755
2856/**
2957 * Implementation of transport over tcp/ip.
3058 */
3159typedef struct
3260{
3361 jerry_debugger_transport_header_t header ; /**< transport header */
34- int tcp_socket ; /**< tcp socket */
62+ jerryx_socket tcp_socket ; /**< tcp socket */
3563} jerryx_debugger_transport_tcp_t ;
3664
65+ /**
66+ * Get the network error value.
67+ *
68+ * On Windows this returns the result of the `WSAGetLastError ()` call and
69+ * on any other system the `errno` value.
70+ *
71+ *
72+ * @return last error value.
73+ */
74+ static inline int
75+ jerryx_debugger_tcp_get_errno (void )
76+ {
77+ #ifdef WIN32
78+ return WSAGetLastError ();
79+ #else /* !WIN32 */
80+ return errno ;
81+ #endif /* WIN32 */
82+ } /* jerryx_debugger_tcp_get_errno */
83+
84+ /**
85+ * Correctly close a single socket.
86+ */
87+ static inline void
88+ jerryx_debugger_tcp_close_socket (jerryx_socket socket_id ) /**< socket to close */
89+ {
90+ #ifdef WIN32
91+ closesocket (socket_id );
92+ #else /* !WIN32 */
93+ close (socket_id );
94+ #endif /* WIN32 */
95+ } /* jerryx_debugger_tcp_close_socket */
96+
3797/**
3898 * Log tcp error message.
3999 */
40100static void
41- jerryx_debugger_tcp_log_error (int err_val )
101+ jerryx_debugger_tcp_log_error (int errno_value ) /**< error value to log */
42102{
43- JERRYX_ERROR_MSG ("TCP Error: %s\n" , strerror (err_val ));
103+ if (errno_value == 0 )
104+ {
105+ return ;
106+ }
107+
108+ #ifdef WIN32
109+ char * error_message = NULL ;
110+ FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS ,
111+ NULL ,
112+ errno_value ,
113+ MAKELANGID (LANG_NEUTRAL , SUBLANG_DEFAULT ),
114+ (LPTSTR ) & error_message ,
115+ 0 ,
116+ NULL );
117+ jerry_port_log (JERRY_LOG_LEVEL_ERROR , "TCP Error: %s\n" , error_message );
118+ LocalFree (error_message );
119+ #else /* !WIN32 */
120+ jerry_port_log (JERRY_LOG_LEVEL_ERROR , "TCP Error: %s\n" , strerror (errno_value ));
121+ #endif /* WIN32 */
44122} /* jerryx_debugger_tcp_log_error */
45123
46124/**
@@ -55,7 +133,7 @@ jerryx_debugger_tcp_close (jerry_debugger_transport_header_t *header_p) /**< tcp
55133
56134 JERRYX_DEBUG_MSG ("TCP connection closed.\n" );
57135
58- close (tcp_p -> tcp_socket );
136+ jerryx_debugger_tcp_close_socket (tcp_p -> tcp_socket );
59137
60138 jerry_heap_free ((void * ) header_p , sizeof (jerryx_debugger_transport_tcp_t ));
61139} /* jerryx_debugger_tcp_close */
@@ -80,7 +158,7 @@ jerryx_debugger_tcp_send (jerry_debugger_transport_header_t *header_p, /**< tcp
80158#ifdef __linux__
81159 ssize_t is_err = recv (tcp_p -> tcp_socket , NULL , 0 , MSG_PEEK );
82160
83- if (is_err == 0 && errno != EWOULDBLOCK )
161+ if (is_err == 0 && errno != JERRYX_EWOULDBLOCK )
84162 {
85163 int err_val = errno ;
86164 jerry_debugger_transport_close ();
@@ -93,12 +171,13 @@ jerryx_debugger_tcp_send (jerry_debugger_transport_header_t *header_p, /**< tcp
93171
94172 if (sent_bytes < 0 )
95173 {
96- if (errno == EWOULDBLOCK )
174+ int err_val = jerryx_debugger_tcp_get_errno ();
175+
176+ if (err_val == JERRYX_EWOULDBLOCK )
97177 {
98178 continue ;
99179 }
100180
101- int err_val = errno ;
102181 jerry_debugger_transport_close ();
103182 jerryx_debugger_tcp_log_error (err_val );
104183 return false;
@@ -128,9 +207,10 @@ jerryx_debugger_tcp_receive (jerry_debugger_transport_header_t *header_p, /**< t
128207
129208 if (length <= 0 )
130209 {
131- if (errno != EWOULDBLOCK || length == 0 )
210+ int err_val = jerryx_debugger_tcp_get_errno ();
211+
212+ if (err_val != JERRYX_EWOULDBLOCK || length == 0 )
132213 {
133- int err_val = errno ;
134214 jerry_debugger_transport_close ();
135215 jerryx_debugger_tcp_log_error (err_val );
136216 return false;
@@ -150,64 +230,104 @@ jerryx_debugger_tcp_receive (jerry_debugger_transport_header_t *header_p, /**< t
150230} /* jerryx_debugger_tcp_receive */
151231
152232/**
153- * Create a tcp connection .
233+ * Utility method to prepare the server socket to accept connections .
154234 *
155- * @return true if successful,
156- * false otherwise
235+ * The following steps are performed:
236+ * * Configure address re-use.
237+ * * Bind the socket to the given port
238+ * * Start listening on the socket.
239+ *
240+ * @return true if everything is ok
241+ * false if there was an error
157242 */
158- bool
159- jerryx_debugger_tcp_create (uint16_t port ) /**< listening port */
243+ static bool
244+ jerryx_debugger_tcp_configure_socket (jerryx_socket server_socket , /** < socket to configure */
245+ uint16_t port ) /** < port number to be used for the socket */
160246{
161- int server_socket ;
162247 struct sockaddr_in addr ;
163- socklen_t sin_size = sizeof (struct sockaddr_in );
164248
165249 addr .sin_family = AF_INET ;
166250 addr .sin_port = htons (port );
167251 addr .sin_addr .s_addr = INADDR_ANY ;
168252
169- if ((server_socket = socket (AF_INET , SOCK_STREAM , 0 )) == -1 )
253+ int opt_value = 1 ;
254+
255+ if (setsockopt (server_socket , SOL_SOCKET , SO_REUSEADDR , & opt_value , sizeof (int )) != 0 )
170256 {
171- JERRYX_ERROR_MSG ("Error: %s\n" , strerror (errno ));
172257 return false;
173258 }
174259
175- int opt_value = 1 ;
260+ if (bind (server_socket , (struct sockaddr * )& addr , sizeof (struct sockaddr_in )) != 0 )
261+ {
262+ return false;
263+ }
176264
177- if (setsockopt (server_socket , SOL_SOCKET , SO_REUSEADDR , & opt_value , sizeof ( int )) == -1 )
265+ if (listen (server_socket , 1 ) != 0 )
178266 {
179- close (server_socket );
180- JERRYX_ERROR_MSG ("Error: %s\n" , strerror (errno ));
181267 return false;
182268 }
183269
184- if (bind (server_socket , (struct sockaddr * )& addr , sizeof (struct sockaddr )) == -1 )
270+ return true;
271+ } /* jerryx_debugger_tcp_configure_socket */
272+
273+ /**
274+ * Create a tcp connection.
275+ *
276+ * @return true if successful,
277+ * false otherwise
278+ */
279+ bool
280+ jerryx_debugger_tcp_create (uint16_t port ) /**< listening port */
281+ {
282+ #ifdef WIN32
283+ WSADATA wsaData ;
284+ int wsa_init_status = WSAStartup (MAKEWORD (2 , 2 ), & wsaData );
285+ if (wsa_init_status != NO_ERROR )
286+ {
287+ JERRYX_ERROR_MSG ("WSA Error: %d\n" , wsa_init_status );
288+ return false;
289+ }
290+ #endif /* WIN32*/
291+
292+ jerryx_socket server_socket = socket (AF_INET , SOCK_STREAM , 0 );
293+ if (server_socket == JERRYX_SOCKET_INVALID )
185294 {
186- close (server_socket );
187- JERRYX_ERROR_MSG ("Error: %s\n" , strerror (errno ));
295+ jerryx_debugger_tcp_log_error (jerryx_debugger_tcp_get_errno ());
188296 return false;
189297 }
190298
191- if (listen (server_socket , 1 ) == -1 )
299+ if (! jerryx_debugger_tcp_configure_socket (server_socket , port ) )
192300 {
193- close (server_socket );
194- JERRYX_ERROR_MSG ("Error: %s\n" , strerror (errno ));
301+ int error = jerryx_debugger_tcp_get_errno ();
302+ jerryx_debugger_tcp_close_socket (server_socket );
303+ jerryx_debugger_tcp_log_error (error );
195304 return false;
196305 }
197306
198307 JERRYX_DEBUG_MSG ("Waiting for client connection\n" );
199308
200- int tcp_socket = accept (server_socket , (struct sockaddr * )& addr , & sin_size );
309+ struct sockaddr_in addr ;
310+ socklen_t sin_size = sizeof (struct sockaddr_in );
311+
312+ jerryx_socket tcp_socket = accept (server_socket , (struct sockaddr * )& addr , & sin_size );
201313
202- close (server_socket );
314+ jerryx_debugger_tcp_close_socket (server_socket );
203315
204- if (tcp_socket == -1 )
316+ if (tcp_socket == JERRYX_SOCKET_INVALID )
205317 {
206- JERRYX_ERROR_MSG ( "Error: %s\n" , strerror ( errno ));
318+ jerryx_debugger_tcp_log_error ( jerryx_debugger_tcp_get_errno ( ));
207319 return false;
208320 }
209321
210322 /* Set non-blocking mode. */
323+ #ifdef WIN32
324+ u_long nonblocking_enabled = 1 ;
325+ if (ioctlsocket (tcp_socket , FIONBIO , & nonblocking_enabled ) != NO_ERROR )
326+ {
327+ jerryx_debugger_tcp_close_socket (tcp_socket );
328+ return false;
329+ }
330+ #else /* !WIN32 */
211331 int socket_flags = fcntl (tcp_socket , F_GETFL , 0 );
212332
213333 if (socket_flags < 0 )
@@ -221,6 +341,7 @@ jerryx_debugger_tcp_create (uint16_t port) /**< listening port */
221341 close (tcp_socket );
222342 return false;
223343 }
344+ #endif /* WIN32 */
224345
225346 JERRYX_DEBUG_MSG ("Connected from: %s\n" , inet_ntoa (addr .sin_addr ));
226347
@@ -231,7 +352,7 @@ jerryx_debugger_tcp_create (uint16_t port) /**< listening port */
231352
232353 if (!header_p )
233354 {
234- close (tcp_socket );
355+ jerryx_debugger_tcp_close_socket (tcp_socket );
235356 return false;
236357 }
237358
0 commit comments