1919
2020#ifdef JERRY_DEBUGGER
2121
22- #include <arpa/inet.h>
2322#include <errno.h>
23+
24+ #if defined (WIN32 )
25+ #include <BaseTsd.h>
26+ typedef SSIZE_T ssize_t ;
27+ #include <WS2tcpip.h>
28+ #include <winsock2.h>
29+
30+ #define JERRYX_EWOULDBLOCK WSAEWOULDBLOCK
31+ #define JERRYX_SOCKET_INVALID INVALID_SOCKET
32+ typedef SOCKET jerryx_socket ;
33+
34+ #else /* !WIN32 */
35+
36+ #include <arpa/inet.h>
2437#include <fcntl.h>
25- #include <unistd.h>
2638#include <sys/socket.h>
39+ #include <unistd.h>
40+
41+ #define JERRYX_EWOULDBLOCK EWOULDBLOCK
42+ #define JERRYX_SOCKET_INVALID (-1)
43+ typedef int jerryx_socket ;
44+ #endif /* WIN32 */
2745
2846/**
2947 * Implementation of transport over tcp/ip.
3048 */
3149typedef struct
3250{
3351 jerry_debugger_transport_header_t header ; /**< transport header */
34- int tcp_socket ; /**< tcp socket */
52+ jerryx_socket tcp_socket ; /**< tcp socket */
3553} jerryx_debugger_transport_tcp_t ;
3654
55+ /**
56+ * Get the network error value.
57+ *
58+ * On Windows this returns the result of the `WSAGetLastError ()` call and
59+ * on any other system the `errno` value.
60+ *
61+ *
62+ * @return last error value.
63+ */
64+ static inline int
65+ jerryx_debugger_tcp_get_errno (void )
66+ {
67+ #ifdef WIN32
68+ return WSAGetLastError ();
69+ #else
70+ return errno ;
71+ #endif
72+ } /* jerryx_debugger_tcp_get_errno */
73+
74+ /**
75+ * Correctly close a single socket.
76+ */
77+ static inline void
78+ jerryx_debugger_tcp_close_socket (jerryx_socket socket_id ) /**< socket to close */
79+ {
80+ #ifdef WIN32
81+ closesocket (socket_id );
82+ #else
83+ close (socket_id );
84+ #endif
85+ } /* jerryx_debugger_tcp_close_socket */
86+
3787/**
3888 * Log tcp error message.
3989 */
4090static void
41- jerryx_debugger_tcp_log_error (int err_val )
91+ jerryx_debugger_tcp_log_error (const char * prefix , /**< message prefix */
92+ int errno_value ) /**< error value to log */
4293{
43- JERRYX_ERROR_MSG ("TCP Error: %s\n" , strerror (err_val ));
94+ #ifdef WIN32
95+ char * error_message = NULL ;
96+ FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS ,
97+ NULL ,
98+ errno_value ,
99+ MAKELANGID (LANG_NEUTRAL , SUBLANG_DEFAULT ),
100+ (LPTSTR ) & error_message ,
101+ 0 ,
102+ NULL );
103+ jerry_port_log (JERRY_LOG_LEVEL_ERROR , "%s: %s\n" , prefix , error_message );
104+ LocalFree (error_message );
105+ #else
106+ jerry_port_log (JERRY_LOG_LEVEL_ERROR , "%s: %s\n" , prefix , strerror (errno_value ));
107+ #endif
44108} /* jerryx_debugger_tcp_log_error */
45109
46110/**
@@ -55,7 +119,7 @@ jerryx_debugger_tcp_close (jerry_debugger_transport_header_t *header_p) /**< tcp
55119
56120 JERRYX_DEBUG_MSG ("TCP connection closed.\n" );
57121
58- close (tcp_p -> tcp_socket );
122+ jerryx_debugger_tcp_close_socket (tcp_p -> tcp_socket );
59123
60124 jerry_heap_free ((void * ) header_p , sizeof (jerryx_debugger_transport_tcp_t ));
61125} /* jerryx_debugger_tcp_close */
@@ -80,11 +144,11 @@ jerryx_debugger_tcp_send (jerry_debugger_transport_header_t *header_p, /**< tcp
80144#ifdef __linux__
81145 ssize_t is_err = recv (tcp_p -> tcp_socket , NULL , 0 , MSG_PEEK );
82146
83- if (is_err == 0 && errno != EWOULDBLOCK )
147+ if (is_err == 0 && errno != JERRYX_EWOULDBLOCK )
84148 {
85149 int err_val = errno ;
86150 jerry_debugger_transport_close ();
87- jerryx_debugger_tcp_log_error (err_val );
151+ jerryx_debugger_tcp_log_error ("TCP Error" , err_val );
88152 return false;
89153 }
90154#endif /* __linux__ */
@@ -93,14 +157,15 @@ jerryx_debugger_tcp_send (jerry_debugger_transport_header_t *header_p, /**< tcp
93157
94158 if (sent_bytes < 0 )
95159 {
96- if (errno == EWOULDBLOCK )
160+ int err_val = jerryx_debugger_tcp_get_errno ();
161+
162+ if (err_val == JERRYX_EWOULDBLOCK )
97163 {
98164 continue ;
99165 }
100166
101- int err_val = errno ;
102167 jerry_debugger_transport_close ();
103- jerryx_debugger_tcp_log_error (err_val );
168+ jerryx_debugger_tcp_log_error ("TCP Error" , err_val );
104169 return false;
105170 }
106171
@@ -128,11 +193,12 @@ jerryx_debugger_tcp_receive (jerry_debugger_transport_header_t *header_p, /**< t
128193
129194 if (length <= 0 )
130195 {
131- if (errno != EWOULDBLOCK || length == 0 )
196+ int err_val = jerryx_debugger_tcp_get_errno ();
197+
198+ if (err_val != JERRYX_EWOULDBLOCK || length == 0 )
132199 {
133- int err_val = errno ;
134200 jerry_debugger_transport_close ();
135- jerryx_debugger_tcp_log_error (err_val );
201+ jerryx_debugger_tcp_log_error ("TCP Error" , err_val );
136202 return false;
137203 }
138204 length = 0 ;
@@ -150,64 +216,105 @@ jerryx_debugger_tcp_receive (jerry_debugger_transport_header_t *header_p, /**< t
150216} /* jerryx_debugger_tcp_receive */
151217
152218/**
153- * Create a tcp connection .
219+ * Utility method to prepare the server socket to accept connections .
154220 *
155- * @return true if successful,
156- * false otherwise
221+ * The following steps are performed:
222+ * * Configure address re-use.
223+ * * Bind the socket to the given port
224+ * * Start listening on the socket.
225+ *
226+ * @return true if everything is ok
227+ * false if there was an error
157228 */
158- bool
159- jerryx_debugger_tcp_create (uint16_t port ) /**< listening port */
229+ static bool
230+ jerryx_debugger_tcp_configure_socket (jerryx_socket server_socket , /** < socket to configure */
231+ uint16_t port ) /** < port number to be used for the socket */
160232{
161- int server_socket ;
162233 struct sockaddr_in addr ;
163- socklen_t sin_size = sizeof (struct sockaddr_in );
164234
165235 addr .sin_family = AF_INET ;
166236 addr .sin_port = htons (port );
167237 addr .sin_addr .s_addr = INADDR_ANY ;
168238
169- if ((server_socket = socket (AF_INET , SOCK_STREAM , 0 )) == -1 )
239+ int opt_value = 1 ;
240+
241+ if (setsockopt (server_socket , SOL_SOCKET , SO_REUSEADDR , & opt_value , sizeof (int )) != 0 )
170242 {
171- JERRYX_ERROR_MSG ("Error: %s\n" , strerror (errno ));
172243 return false;
173244 }
174245
175- int opt_value = 1 ;
246+ if (bind (server_socket , (struct sockaddr * )& addr , sizeof (struct sockaddr )) != 0 )
247+ {
248+ return false;
249+ }
176250
177- if (setsockopt (server_socket , SOL_SOCKET , SO_REUSEADDR , & opt_value , sizeof (int )) == -1 )
251+ if (listen (server_socket , 1 ) != 0 )
252+ {
253+ return false;
254+ }
255+
256+ return true;
257+ } /* jerryx_debugger_tcp_configure_socket */
258+
259+ /**
260+ * Create a tcp connection.
261+ *
262+ * @return true if successful,
263+ * false otherwise
264+ */
265+ bool
266+ jerryx_debugger_tcp_create (uint16_t port ) /**< listening port */
267+ {
268+ #ifdef WIN32
269+ WSADATA wsaData ;
270+ int wsa_init_status = WSAStartup (MAKEWORD (2 , 2 ), & wsaData );
271+ if (wsa_init_status != NO_ERROR )
178272 {
179- close (server_socket );
180- JERRYX_ERROR_MSG ("Error: %s\n" , strerror (errno ));
273+ JERRYX_ERROR_MSG ("WSA Error: %d\n" , wsa_init_status );
181274 return false;
182275 }
276+ #endif
183277
184- if (bind (server_socket , (struct sockaddr * )& addr , sizeof (struct sockaddr )) == -1 )
278+ jerryx_socket server_socket = socket (AF_INET , SOCK_STREAM , 0 );
279+ if (server_socket == JERRYX_SOCKET_INVALID )
185280 {
186- close (server_socket );
187- JERRYX_ERROR_MSG ("Error: %s\n" , strerror (errno ));
281+ jerryx_debugger_tcp_log_error ("Error" , jerryx_debugger_tcp_get_errno ());
188282 return false;
189283 }
190284
191- if (listen (server_socket , 1 ) == -1 )
285+ if (! jerryx_debugger_tcp_configure_socket (server_socket , port ) )
192286 {
193- close (server_socket );
194- JERRYX_ERROR_MSG ("Error: %s\n" , strerror (errno ));
287+ int error = jerryx_debugger_tcp_get_errno ();
288+ jerryx_debugger_tcp_close_socket (server_socket );
289+ jerryx_debugger_tcp_log_error ("Error" , error );
195290 return false;
196291 }
197292
198293 JERRYX_DEBUG_MSG ("Waiting for client connection\n" );
199294
200- int tcp_socket = accept (server_socket , (struct sockaddr * )& addr , & sin_size );
295+ struct sockaddr_in addr ;
296+ socklen_t sin_size = sizeof (struct sockaddr_in );
201297
202- close (server_socket );
298+ jerryx_socket tcp_socket = accept (server_socket , ( struct sockaddr * ) & addr , & sin_size );
203299
204- if (tcp_socket == -1 )
300+ jerryx_debugger_tcp_close_socket (server_socket );
301+
302+ if (tcp_socket == JERRYX_SOCKET_INVALID )
205303 {
206- JERRYX_ERROR_MSG ("Error: %s\n" , strerror (errno ));
304+ int error = jerryx_debugger_tcp_get_errno ();
305+ jerryx_debugger_tcp_log_error ("Error" , error );
207306 return false;
208307 }
209308
210309 /* Set non-blocking mode. */
310+ #ifdef WIN32
311+ u_long nonblocking_enabled = TRUE;
312+ if (ioctlsocket (tcp_socket , FIONBIO , & nonblocking_enabled ) != NO_ERROR )
313+ {
314+ jerryx_debugger_tcp_close_socket (tcp_socket );
315+ return false;
316+ }
317+ #else
211318 int socket_flags = fcntl (tcp_socket , F_GETFL , 0 );
212319
213320 if (socket_flags < 0 )
@@ -221,6 +328,7 @@ jerryx_debugger_tcp_create (uint16_t port) /**< listening port */
221328 close (tcp_socket );
222329 return false;
223330 }
331+ #endif
224332
225333 JERRYX_DEBUG_MSG ("Connected from: %s\n" , inet_ntoa (addr .sin_addr ));
226334
@@ -231,7 +339,7 @@ jerryx_debugger_tcp_create (uint16_t port) /**< listening port */
231339
232340 if (!header_p )
233341 {
234- close (tcp_socket );
342+ jerryx_debugger_tcp_close_socket (tcp_socket );
235343 return false;
236344 }
237345
0 commit comments