]> git.saurik.com Git - wxWidgets.git/blame - src/msw/gsocket.c
with only a little modification could be generic
[wxWidgets.git] / src / msw / gsocket.c
CommitLineData
9bbd7ba3
GRG
1/* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
3 * Name: gsocket.c
4 * Purpose: GSocket main MSW file
5 * CVSID: $Id$
6 * -------------------------------------------------------------------------
7 */
8
2f7c2af5 9#ifndef __GSOCKET_STANDALONE__
9bbd7ba3 10#include "wx/setup.h"
0ce742cf
GRG
11#endif
12
13#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
14
15
16#ifndef __GSOCKET_STANDALONE__
17
9bbd7ba3
GRG
18#include "wx/msw/gsockmsw.h"
19#include "wx/gsocket.h"
20
eb254be6 21#define INSTANCE wxGetInstance()
9bbd7ba3
GRG
22
23#else
24
25#include "gsockmsw.h"
26#include "gsocket.h"
27
28/* If not using wxWindows, a global var called hInst must
29 * be available and it must containt the app's instance
30 * handle.
31 */
b661e675 32#define INSTANCE hInst
9bbd7ba3 33
2f7c2af5 34#endif /* __GSOCKET_STANDALONE__ */
9bbd7ba3
GRG
35
36
9bbd7ba3
GRG
37#include <assert.h>
38#include <string.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <stddef.h>
42#include <ctype.h>
43#include <winsock.h>
44
45#define SOCKLEN_T int
46#define CLASSNAME "_GSocket_Internal_Window_Class"
47#define WINDOWNAME "_GSocket_Internal_Window_Name"
48
49/* Maximum number of different GSocket objects at a given time.
50 * This value can be modified at will, but it CANNOT be greater
51 * than (0x7FFF - WM_USER + 1)
52 */
53#define MAXSOCKETS 1024
54
55#if (MAXSOCKETS > (0x7FFF - WM_USER + 1))
56#error "MAXSOCKETS is too big!"
57#endif
58
59
60/* Global variables */
61
62extern HINSTANCE INSTANCE;
63static HWND hWin;
64static CRITICAL_SECTION critical;
65static GSocket* socketList[MAXSOCKETS];
66static int firstAvailable;
67
68/* Global initializers */
69
70bool GSocket_Init()
71{
72 WSADATA wsaData;
73 WNDCLASS winClass;
74 int i;
75
76 /* Create internal window for event notifications */
77 winClass.style = 0;
78 winClass.lpfnWndProc = _GSocket_Internal_WinProc;
79 winClass.cbClsExtra = 0;
80 winClass.cbWndExtra = 0;
81 winClass.hInstance = INSTANCE;
82 winClass.hIcon = (HICON) NULL;
83 winClass.hCursor = (HCURSOR) NULL;
84 winClass.hbrBackground = (HBRUSH) NULL;
85 winClass.lpszMenuName = (LPCTSTR) NULL;
86 winClass.lpszClassName = CLASSNAME;
87
88 RegisterClass(&winClass);
89 hWin = CreateWindow(CLASSNAME,
90 WINDOWNAME,
91 0, 0, 0, 0, 0,
92 (HWND) NULL, (HMENU) NULL, INSTANCE, (LPVOID) NULL);
93
94 if (!hWin) return FALSE;
95
96 /* Initialize socket list */
97 InitializeCriticalSection(&critical);
98
99 for (i = 0; i < MAXSOCKETS; i++)
100 {
101 socketList[i] = NULL;
102 }
103 firstAvailable = 0;
104
9bbd7ba3
GRG
105 /* Initialize WinSocket */
106 return (WSAStartup((1 << 8) | 1, &wsaData) == 0);
107}
108
109void GSocket_Cleanup()
110{
111 /* Destroy internal window */
aa3981f2 112 DestroyWindow(hWin);
9bbd7ba3
GRG
113 UnregisterClass(CLASSNAME, INSTANCE);
114
115 /* Delete critical section */
116 DeleteCriticalSection(&critical);
117
118 /* Cleanup WinSocket */
119 WSACleanup();
120}
121
122/* Constructors / Destructors */
123
124GSocket *GSocket_new()
125{
126 int i;
127 GSocket *socket;
128
129 if ((socket = (GSocket *) malloc(sizeof(GSocket))) == NULL)
130 return NULL;
131
132 socket->m_fd = INVALID_SOCKET;
133 for (i = 0; i < GSOCK_MAX_EVENT; i++)
134 {
135 socket->m_cbacks[i] = NULL;
136 }
137 socket->m_local = NULL;
138 socket->m_peer = NULL;
139 socket->m_error = GSOCK_NOERROR;
140 socket->m_server = FALSE;
141 socket->m_stream = TRUE;
142 socket->m_non_blocking = FALSE;
143 socket->m_timeout.tv_sec = 10 * 60; /* 10 minutes */
b661e675 144 socket->m_timeout.tv_usec = 0;
75d684d9 145 socket->m_detected = 0;
9bbd7ba3
GRG
146
147 /* Allocate a new message number for this socket */
148 EnterCriticalSection(&critical);
149
150 i = firstAvailable;
151 while (socketList[i] != NULL)
152 {
153 i = (i + 1) % MAXSOCKETS;
154
155 if (i == firstAvailable) /* abort! */
156 {
157 free(socket);
158 LeaveCriticalSection(&critical);
159 return NULL;
160 }
161 }
162 socketList[i] = socket;
163 firstAvailable = (i + 1) % MAXSOCKETS;
164 socket->m_msgnumber = (i + WM_USER);
165
166 LeaveCriticalSection(&critical);
167
168 return socket;
169}
170
171void GSocket_destroy(GSocket *socket)
172{
173 assert(socket != NULL);
174
75d684d9 175 /* Remove the socket from the list */
9bbd7ba3
GRG
176 EnterCriticalSection(&critical);
177 socketList[(socket->m_msgnumber - WM_USER)] = NULL;
178 LeaveCriticalSection(&critical);
179
75d684d9 180 /* Check that the socket is really shutdowned */
9bbd7ba3
GRG
181 if (socket->m_fd != INVALID_SOCKET)
182 GSocket_Shutdown(socket);
183
75d684d9 184 /* Destroy private addresses */
9bbd7ba3
GRG
185 if (socket->m_local)
186 GAddress_destroy(socket->m_local);
187
188 if (socket->m_peer)
189 GAddress_destroy(socket->m_peer);
190
75d684d9 191 /* Destroy socket itself */
9bbd7ba3
GRG
192 free(socket);
193}
194
195void GSocket_Shutdown(GSocket *socket)
196{
197 int evt;
198
199 assert(socket != NULL);
200
75d684d9 201 /* If socket has been created, shutdown it */
9bbd7ba3
GRG
202 if (socket->m_fd != INVALID_SOCKET)
203 {
9bbd7ba3
GRG
204 shutdown(socket->m_fd, 2);
205 closesocket(socket->m_fd);
206 socket->m_fd = INVALID_SOCKET;
207 }
208
75d684d9 209 /* Disable GUI callbacks */
9bbd7ba3 210 for (evt = 0; evt < GSOCK_MAX_EVENT; evt++)
9bbd7ba3 211 socket->m_cbacks[evt] = NULL;
9bbd7ba3 212
75d684d9
GRG
213 socket->m_detected = 0;
214 _GSocket_Disable_Events(socket);
9bbd7ba3
GRG
215}
216
217/* Address handling */
218
219GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address)
220{
221 assert(socket != NULL);
222
223 if (socket->m_fd != INVALID_SOCKET && !socket->m_server)
224 {
225 socket->m_error = GSOCK_INVSOCK;
226 return GSOCK_INVSOCK;
227 }
228
229 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
230 {
231 socket->m_error = GSOCK_INVADDR;
232 return GSOCK_INVADDR;
233 }
234
235 if (socket->m_local)
236 GAddress_destroy(socket->m_local);
237
238 socket->m_local = GAddress_copy(address);
239
240 return GSOCK_NOERROR;
241}
242
243GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address)
244{
245 assert(socket != NULL);
246
247 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
248 {
249 socket->m_error = GSOCK_INVADDR;
250 return GSOCK_INVADDR;
251 }
252
253 if (socket->m_peer)
254 GAddress_destroy(socket->m_peer);
255
256 socket->m_peer = GAddress_copy(address);
257
258 return GSOCK_NOERROR;
259}
260
261GAddress *GSocket_GetLocal(GSocket *socket)
262{
263 GAddress *address;
264 struct sockaddr addr;
265 SOCKLEN_T size;
266
267 assert(socket != NULL);
268
269 if (socket->m_local)
270 return GAddress_copy(socket->m_local);
271
272 if (socket->m_fd == INVALID_SOCKET)
273 {
274 socket->m_error = GSOCK_INVSOCK;
275 return NULL;
276 }
277
278 size = sizeof(addr);
279
280 if (getsockname(socket->m_fd, &addr, &size) == SOCKET_ERROR)
281 {
282 socket->m_error = GSOCK_IOERR;
283 return NULL;
284 }
285
286 address = GAddress_new();
287 if (address == NULL)
288 {
289 socket->m_error = GSOCK_MEMERR;
290 return NULL;
291 }
292 if (_GAddress_translate_from(address, &addr, size) != GSOCK_NOERROR)
293 {
294 socket->m_error = GSOCK_MEMERR;
295 GAddress_destroy(address);
296 return NULL;
297 }
298
299 return address;
300}
301
302GAddress *GSocket_GetPeer(GSocket *socket)
303{
304 assert(socket != NULL);
305
306 if (socket->m_peer)
307 return GAddress_copy(socket->m_peer);
308
309 return NULL;
310}
311
312/* Server specific parts */
313
314/* GSocket_SetServer:
315 * Sets up the socket as a server. It uses the "Local" field of GSocket.
316 * "Local" must be set by GSocket_SetLocal() before GSocket_SetServer()
317 * is called. Possible error codes are: GSOCK_INVSOCK if socket has not
318 * been initialized, GSOCK_INVADDR if the local address has not been
319 * defined and GSOCK_IOERR for other internal errors.
320 */
321GSocketError GSocket_SetServer(GSocket *sck)
322{
323 u_long arg = 1;
324
325 assert(sck != NULL);
326
327 if (sck->m_fd != INVALID_SOCKET)
328 {
329 sck->m_error = GSOCK_INVSOCK;
330 return GSOCK_INVSOCK;
331 }
332
333 if (!sck->m_local)
334 {
335 sck->m_error = GSOCK_INVADDR;
336 return GSOCK_INVADDR;
337 }
338
339 /* Initialize all fields */
340 sck->m_server = TRUE;
341 sck->m_stream = TRUE;
342 sck->m_oriented = TRUE;
343
344 /* Create the socket */
345 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_STREAM, 0);
9bbd7ba3
GRG
346
347 if (sck->m_fd == INVALID_SOCKET)
348 {
349 sck->m_error = GSOCK_IOERR;
350 return GSOCK_IOERR;
351 }
352
483c6690 353 ioctlsocket(sck->m_fd, FIONBIO, (u_long FAR *) &arg);
75d684d9 354 _GSocket_Enable_Events(sck);
483c6690 355
9bbd7ba3
GRG
356 /* Bind the socket to the LOCAL address */
357 if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) != 0)
358 {
359 closesocket(sck->m_fd);
360 sck->m_fd = INVALID_SOCKET;
361 sck->m_error = GSOCK_IOERR;
362 return GSOCK_IOERR;
363 }
364
365 /* Enable listening up to 5 connections */
366 if (listen(sck->m_fd, 5) != 0)
367 {
368 closesocket(sck->m_fd);
369 sck->m_fd = INVALID_SOCKET;
370 sck->m_error = GSOCK_IOERR;
371 return GSOCK_IOERR;
372 }
373
374 return GSOCK_NOERROR;
b661e675 375}
9bbd7ba3
GRG
376
377/* GSocket_WaitConnection:
378 * Waits for an incoming client connection.
379 */
380GSocket *GSocket_WaitConnection(GSocket *sck)
381{
382 GSocket *connection;
383 u_long arg = 1;
384
385 assert(sck != NULL);
386
75d684d9
GRG
387 sck->m_detected &= ~GSOCK_CONNECTION_FLAG;
388
9bbd7ba3
GRG
389 if (sck->m_fd == INVALID_SOCKET || !sck->m_server)
390 {
391 sck->m_error = GSOCK_INVSOCK;
392 return NULL;
393 }
394
395 /* Create a GSocket object for the new connection */
396 connection = GSocket_new();
397
398 if (!connection)
399 {
400 sck->m_error = GSOCK_MEMERR;
401 return NULL;
402 }
403
404 /* Wait for a connection (with timeout) */
405 if (_GSocket_Input_Timeout(sck) == GSOCK_TIMEDOUT)
406 {
407 GSocket_destroy(connection);
408 /* sck->m_error set by _GSocket_Input_Timeout */
409 return NULL;
410 }
411
412 connection->m_fd = accept(sck->m_fd, NULL, NULL);
9bbd7ba3
GRG
413
414 if (connection->m_fd == INVALID_SOCKET)
415 {
aa3981f2
GRG
416 if (WSAGetLastError() == WSAEWOULDBLOCK)
417 sck->m_error = GSOCK_WOULDBLOCK;
418 else
419 sck->m_error = GSOCK_IOERR;
420
9bbd7ba3 421 GSocket_destroy(connection);
9bbd7ba3
GRG
422 return NULL;
423 }
424
425 /* Initialize all fields */
426 connection->m_server = FALSE;
427 connection->m_stream = TRUE;
428 connection->m_oriented = TRUE;
429
cb421e53 430 ioctlsocket(connection->m_fd, FIONBIO, (u_long FAR *) &arg);
75d684d9 431 _GSocket_Enable_Events(connection);
cb421e53 432
9bbd7ba3
GRG
433 return connection;
434}
435
436/* Non oriented connections */
437
438GSocketError GSocket_SetNonOriented(GSocket *sck)
439{
440 u_long arg = 1;
441
442 assert(sck != NULL);
443
444 if (sck->m_fd != INVALID_SOCKET)
445 {
446 sck->m_error = GSOCK_INVSOCK;
447 return GSOCK_INVSOCK;
448 }
449
450 if (!sck->m_local)
451 {
452 sck->m_error = GSOCK_INVADDR;
453 return GSOCK_INVADDR;
454 }
455
456 /* Initialize all fields */
457 sck->m_stream = FALSE;
458 sck->m_server = FALSE;
459 sck->m_oriented = FALSE;
460
461 /* Create the socket */
462 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0);
9bbd7ba3
GRG
463
464 if (sck->m_fd == INVALID_SOCKET)
465 {
466 sck->m_error = GSOCK_IOERR;
467 return GSOCK_IOERR;
468 }
469
483c6690 470 ioctlsocket(sck->m_fd, FIONBIO, (u_long FAR *) &arg);
75d684d9 471 _GSocket_Enable_Events(sck);
483c6690 472
9bbd7ba3
GRG
473 /* Bind it to the LOCAL address */
474 if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) != 0)
475 {
476 closesocket(sck->m_fd);
477 sck->m_fd = INVALID_SOCKET;
478 sck->m_error = GSOCK_IOERR;
479 return GSOCK_IOERR;
480 }
481
482 return GSOCK_NOERROR;
483}
484
485GSocketError GSocket_SetBroadcast(GSocket *sck)
486{
75d684d9 487 BOOL b = TRUE;
9bbd7ba3
GRG
488
489 assert(sck != NULL);
490
491 if (GSocket_SetNonOriented(sck) != GSOCK_NOERROR)
492 return sck->m_error;
493
75d684d9
GRG
494 setsockopt(sck->m_fd, SOL_SOCKET, SO_BROADCAST,
495 (const char FAR *) &b, sizeof(b));
9bbd7ba3
GRG
496
497 return GSOCK_NOERROR;
498}
499
500/* Client specific parts */
501
502/* GSocket_Connect:
503 * Establishes a client connection to a server using the "Peer"
504 * field of GSocket. "Peer" must be set by GSocket_SetPeer() before
cb421e53
GRG
505 * GSocket_Connect() is called. Possible error codes are GSOCK_INVSOCK,
506 * GSOCK_INVADDR, GSOCK_TIMEDOUT, GSOCK_WOULDBLOCK and GSOCK_IOERR.
483c6690
GRG
507 * If a socket is nonblocking and Connect() returns GSOCK_WOULDBLOCK,
508 * the connection request can be completed later. Use GSocket_Select()
509 * to check or wait for a GSOCK_CONNECTION event.
9bbd7ba3
GRG
510 */
511GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
512{
513 u_long arg = 1;
aa3981f2 514 int type, ret, err;
9bbd7ba3
GRG
515
516 assert(sck != NULL);
517
75d684d9
GRG
518 sck->m_detected &= ~GSOCK_CONNECTION_FLAG;
519
9bbd7ba3
GRG
520 if (sck->m_fd != INVALID_SOCKET)
521 {
522 sck->m_error = GSOCK_INVSOCK;
523 return GSOCK_INVSOCK;
524 }
525
526 if (!sck->m_peer)
527 {
528 sck->m_error = GSOCK_INVADDR;
529 return GSOCK_INVADDR;
530 }
531
532 /* Test whether we want the socket to be a stream (e.g. TCP) */
533 sck->m_stream = (stream == GSOCK_STREAMED);
534 sck->m_oriented = TRUE;
535 sck->m_server = FALSE;
536
537 if (sck->m_stream)
538 type = SOCK_STREAM;
539 else
540 type = SOCK_DGRAM;
541
542 /* Create the socket */
543 sck->m_fd = socket(sck->m_peer->m_realfamily, type, 0);
9bbd7ba3
GRG
544
545 if (sck->m_fd == INVALID_SOCKET)
546 {
547 sck->m_error = GSOCK_IOERR;
548 return GSOCK_IOERR;
549 }
550
483c6690 551 ioctlsocket(sck->m_fd, FIONBIO, (u_long FAR *) &arg);
75d684d9 552 _GSocket_Enable_Events(sck);
483c6690 553
aa3981f2 554 /* Connect it to the PEER address, with a timeout (see below) */
9bbd7ba3
GRG
555 ret = connect(sck->m_fd, sck->m_peer->m_addr, sck->m_peer->m_len);
556
557 if (ret == SOCKET_ERROR)
558 {
aa3981f2
GRG
559 err = WSAGetLastError();
560
561 /* If connect failed with EWOULDBLOCK and the GSocket object
562 * is in blocking mode, we select() for the specified timeout
563 * checking for writability to see if the connection request
564 * completes.
9bbd7ba3 565 */
cb421e53 566 if ((err == WSAEWOULDBLOCK) && (!sck->m_non_blocking))
9bbd7ba3
GRG
567 {
568 if (_GSocket_Output_Timeout(sck) == GSOCK_TIMEDOUT)
569 {
570 closesocket(sck->m_fd);
571 sck->m_fd = INVALID_SOCKET;
cb421e53 572 /* sck->m_error is set in _GSocket_Output_Timeout */
9bbd7ba3
GRG
573 return GSOCK_TIMEDOUT;
574 }
aa3981f2
GRG
575 else
576 return GSOCK_NOERROR;
9bbd7ba3 577 }
aa3981f2
GRG
578
579 /* If connect failed with EWOULDBLOCK and the GSocket object
580 * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK
581 * (and return GSOCK_WOULDBLOCK) but we don't close the socket;
582 * this way if the connection completes, a GSOCK_CONNECTION
583 * event will be generated, if enabled.
584 */
cb421e53 585 if ((err == WSAEWOULDBLOCK) && (sck->m_non_blocking))
9bbd7ba3 586 {
aa3981f2
GRG
587 sck->m_error = GSOCK_WOULDBLOCK;
588 return GSOCK_WOULDBLOCK;
9bbd7ba3 589 }
aa3981f2
GRG
590
591 /* If connect failed with an error other than EWOULDBLOCK,
592 * then the call to GSocket_Connect has failed.
593 */
594 closesocket(sck->m_fd);
595 sck->m_fd = INVALID_SOCKET;
596 sck->m_error = GSOCK_IOERR;
597 return GSOCK_IOERR;
9bbd7ba3
GRG
598 }
599
600 return GSOCK_NOERROR;
601}
602
603/* Generic IO */
604
605/* Like recv(), send(), ... */
606int GSocket_Read(GSocket *socket, char *buffer, int size)
607{
75d684d9
GRG
608 int ret;
609
9bbd7ba3
GRG
610 assert(socket != NULL);
611
75d684d9
GRG
612 socket->m_detected &= ~GSOCK_INPUT_FLAG;
613
9bbd7ba3
GRG
614 if (socket->m_fd == INVALID_SOCKET || socket->m_server)
615 {
616 socket->m_error = GSOCK_INVSOCK;
617 return -1;
618 }
619
75d684d9 620 /* If the socket is blocking, wait for data (with a timeout) */
9bbd7ba3
GRG
621 if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT)
622 return -1;
623
75d684d9 624 /* Read the data */
9bbd7ba3 625 if (socket->m_stream)
75d684d9 626 ret = _GSocket_Recv_Stream(socket, buffer, size);
9bbd7ba3 627 else
75d684d9
GRG
628 ret = _GSocket_Recv_Dgram(socket, buffer, size);
629
630 if (ret == SOCKET_ERROR)
631 {
632 /* NOTE: Window sockets exhibit a very strange property;
633 * if the socket is in non-blocking mode (which is always
634 * the case here, no matter the setting of GSocket itself)
635 * a call to send() can fail with EWOULDBLOCK even when
636 * select() says that the socket is readable.
637 *
638 * This can break several things because, usually, if
639 * select() says that the socket is writable, it is
640 * assumed that send() won't fail. To avoid this, we
641 * return 0 instead of -1 for this special case.
642 */
643 if (WSAGetLastError() != WSAEWOULDBLOCK)
644 {
645 socket->m_error = GSOCK_IOERR;
646 return -1;
647 }
648 else
649 {
650 socket->m_error = GSOCK_WOULDBLOCK;
651 return 0;
652 }
653 }
654
655 return ret;
9bbd7ba3
GRG
656}
657
658int GSocket_Write(GSocket *socket, const char *buffer, int size)
659{
75d684d9
GRG
660 int ret;
661
9bbd7ba3
GRG
662 assert(socket != NULL);
663
664 if (socket->m_fd == INVALID_SOCKET || socket->m_server)
665 {
666 socket->m_error = GSOCK_INVSOCK;
667 return -1;
668 }
669
75d684d9 670 /* If the socket is blocking, wait for writability (with a timeout) */
9bbd7ba3
GRG
671 if (_GSocket_Output_Timeout(socket) == GSOCK_TIMEDOUT)
672 return -1;
673
75d684d9 674 /* Read the data */
9bbd7ba3 675 if (socket->m_stream)
75d684d9 676 ret = _GSocket_Send_Stream(socket, buffer, size);
9bbd7ba3 677 else
75d684d9
GRG
678 ret = _GSocket_Send_Dgram(socket, buffer, size);
679
680 if (ret == SOCKET_ERROR)
681 {
682 if (WSAGetLastError() != WSAEWOULDBLOCK)
683 socket->m_error = GSOCK_IOERR;
684 else
685 socket->m_error = GSOCK_WOULDBLOCK;
686
687 socket->m_detected &= ~GSOCK_OUTPUT_FLAG;
688 return -1;
689 }
690
691 return ret;
9bbd7ba3
GRG
692}
693
483c6690
GRG
694/* GSocket_Select:
695 * Polls the socket to determine its status. This function will
696 * check for the events specified in the 'flags' parameter, and
697 * it will return a mask indicating which operations can be
698 * performed. This function won't block, regardless of the
699 * mode (blocking|nonblocking) of the socket.
700 */
701GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
9bbd7ba3 702{
9bbd7ba3
GRG
703 assert(socket != NULL);
704
75d684d9 705 return (flags & socket->m_detected);
9bbd7ba3
GRG
706}
707
708/* Flags */
709
710/* GSocket_SetNonBlocking:
483c6690 711 * Sets the socket to non-blocking mode. This is useful if
9bbd7ba3
GRG
712 * we don't want to wait.
713 */
714void GSocket_SetNonBlocking(GSocket *socket, bool non_block)
715{
716 assert(socket != NULL);
717
718 socket->m_non_blocking = non_block;
719}
720
721/* GSocket_SetTimeout:
483c6690
GRG
722 * Sets the timeout for blocking calls. Time is
723 * expressed in milliseconds.
9bbd7ba3 724 */
75d684d9 725void GSocket_SetTimeout(GSocket *socket, unsigned long millis)
9bbd7ba3
GRG
726{
727 assert(socket != NULL);
728
75d684d9
GRG
729 socket->m_timeout.tv_sec = (millis / 1000);
730 socket->m_timeout.tv_usec = (millis % 1000) * 1000;
9bbd7ba3
GRG
731}
732
733/* GSocket_GetError:
734 * Returns the last error occured for this socket.
735 */
736GSocketError GSocket_GetError(GSocket *socket)
737{
738 assert(socket != NULL);
739
740 return socket->m_error;
741}
742
743/* Callbacks */
744
745/* Only one callback is possible for each event (INPUT, OUTPUT, CONNECTION
746 * and LOST). The callbacks are called in the following situations:
747 *
748 * INPUT: There is at least one byte in the input buffer
749 * OUTPUT: The system is sure that the next write call will not block
750 * CONNECTION: Two cases are possible:
751 * Client socket -> the connection is established
752 * Server socket -> a client requests a connection
753 * LOST: The connection is lost
754 *
755 * An event is generated only once and its state is reseted when the
756 * relative IO call is requested.
757 * For example: INPUT -> GSocket_Read()
758 * CONNECTION -> GSocket_Accept()
759 */
760
761/* GSocket_SetCallback:
483c6690 762 * Enables the callbacks specified by 'flags'. Note that 'flags'
9bbd7ba3
GRG
763 * may be a combination of flags OR'ed toghether, so the same
764 * callback function can be made to accept different events.
765 * The callback function must have the following prototype:
766 *
767 * void function(GSocket *socket, GSocketEvent event, char *cdata)
768 */
483c6690 769void GSocket_SetCallback(GSocket *socket, GSocketEventFlags flags,
9bbd7ba3
GRG
770 GSocketCallback callback, char *cdata)
771{
772 int count;
773
774 assert (socket != NULL);
775
776 for (count = 0; count < GSOCK_MAX_EVENT; count++)
777 {
483c6690 778 if ((flags & (1 << count)) != 0)
9bbd7ba3
GRG
779 {
780 socket->m_cbacks[count] = callback;
781 socket->m_data[count] = cdata;
782 }
783 }
9bbd7ba3
GRG
784}
785
786/* GSocket_UnsetCallback:
483c6690 787 * Disables all callbacks specified by 'flags', which may be a
9bbd7ba3
GRG
788 * combination of flags OR'ed toghether.
789 */
483c6690 790void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags)
9bbd7ba3
GRG
791{
792 int count = 0;
793
794 assert(socket != NULL);
795
796 for (count = 0; count < GSOCK_MAX_EVENT; count++)
797 {
483c6690 798 if ((flags & (1 << count)) != 0)
9bbd7ba3
GRG
799 {
800 socket->m_cbacks[count] = NULL;
75d684d9 801 socket->m_data[count] = NULL;
9bbd7ba3
GRG
802 }
803 }
9bbd7ba3
GRG
804}
805
806
807/* Internals */
808
75d684d9
GRG
809/* _GSocket_Enable_Events:
810 * We enable all event notifications here (we need to be notified
811 * of all events for internal processing) but we will only notify
812 * users when an appropiate callback function has been installed.
813 */
814void _GSocket_Enable_Events(GSocket *socket)
9bbd7ba3 815{
75d684d9 816 assert (socket != NULL);
483c6690 817
75d684d9 818 if (socket->m_fd != INVALID_SOCKET)
9bbd7ba3 819 {
75d684d9
GRG
820 WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber,
821 FD_READ | FD_WRITE | FD_ACCEPT | FD_CONNECT | FD_CLOSE);
9bbd7ba3 822 }
75d684d9
GRG
823}
824
825/* _GSocket_Disable_Events:
826 * Disable event notifications (when shutdowning the socket)
827 */
828void _GSocket_Disable_Events(GSocket *socket)
829{
830 assert (socket != NULL);
9bbd7ba3 831
75d684d9
GRG
832 if (socket->m_fd != INVALID_SOCKET)
833 {
834 WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, 0);
835 }
9bbd7ba3
GRG
836}
837
75d684d9 838
9bbd7ba3
GRG
839LRESULT CALLBACK _GSocket_Internal_WinProc(HWND hWnd,
840 UINT uMsg,
841 WPARAM wParam,
842 LPARAM lParam)
843{
844 GSocket *socket;
845 GSocketEvent event;
846 GSocketCallback cback;
75d684d9 847 char *data;
9bbd7ba3
GRG
848
849 if (uMsg >= WM_USER && uMsg <= (WM_USER + MAXSOCKETS - 1))
850 {
851 EnterCriticalSection(&critical);
852 socket = socketList[(uMsg - WM_USER)];
853 event = -1;
854 cback = NULL;
75d684d9 855 data = NULL;
9bbd7ba3
GRG
856
857 /* Check that the socket still exists (it has not been
858 * destroyed) and for safety, check that the m_fd field
859 * is what we expect it to be.
860 */
861 if ((socket != NULL) && (socket->m_fd == wParam))
862 {
863 switch WSAGETSELECTEVENT(lParam)
864 {
865 case FD_READ: event = GSOCK_INPUT; break;
866 case FD_WRITE: event = GSOCK_OUTPUT; break;
867 case FD_ACCEPT: event = GSOCK_CONNECTION; break;
cb421e53
GRG
868 case FD_CONNECT:
869 {
870 if (WSAGETSELECTERROR(lParam) != 0)
871 event = GSOCK_LOST;
872 else
873 event = GSOCK_CONNECTION;
874 break;
875 }
9bbd7ba3
GRG
876 case FD_CLOSE: event = GSOCK_LOST; break;
877 }
878
879 if (event != -1)
75d684d9 880 {
9bbd7ba3 881 cback = socket->m_cbacks[event];
75d684d9
GRG
882 data = socket->m_data[event];
883
884 if (event == GSOCK_LOST)
885 socket->m_detected = GSOCK_LOST_FLAG;
886 else
887 socket->m_detected |= (1 << event);
888 }
9bbd7ba3
GRG
889 }
890
891 /* OK, we can now leave the critical section because we have
892 * already obtained the callback address (we make no further
893 * accesses to socket->whatever)
894 */
895 LeaveCriticalSection(&critical);
896
897 if (cback != NULL)
75d684d9 898 (cback)(socket, event, data);
9bbd7ba3
GRG
899
900 return (LRESULT) 0;
901 }
902 else
903 return DefWindowProc(hWnd, uMsg, wParam, lParam);
904}
905
906
907/* _GSocket_Input_Timeout:
908 * For blocking sockets, wait until data is available or
909 * until timeout ellapses.
910 */
911GSocketError _GSocket_Input_Timeout(GSocket *socket)
912{
913 fd_set readfds;
914
cb421e53 915 if (!socket->m_non_blocking)
9bbd7ba3
GRG
916 {
917 FD_ZERO(&readfds);
918 FD_SET(socket->m_fd, &readfds);
919 if (select(0, &readfds, NULL, NULL, &socket->m_timeout) == 0)
920 {
921 socket->m_error = GSOCK_TIMEDOUT;
922 return GSOCK_TIMEDOUT;
923 }
924 }
925 return GSOCK_NOERROR;
926}
927
928/* _GSocket_Output_Timeout:
929 * For blocking sockets, wait until data can be sent without
930 * blocking or until timeout ellapses.
931 */
932GSocketError _GSocket_Output_Timeout(GSocket *socket)
933{
934 fd_set writefds;
935
cb421e53 936 if (!socket->m_non_blocking)
9bbd7ba3
GRG
937 {
938 FD_ZERO(&writefds);
939 FD_SET(socket->m_fd, &writefds);
940 if (select(0, NULL, &writefds, NULL, &socket->m_timeout) == 0)
941 {
942 socket->m_error = GSOCK_TIMEDOUT;
943 return GSOCK_TIMEDOUT;
944 }
945 }
946 return GSOCK_NOERROR;
947}
948
949int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
950{
75d684d9 951 return recv(socket->m_fd, buffer, size, 0);
9bbd7ba3
GRG
952}
953
954int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size)
955{
956 struct sockaddr from;
75d684d9 957 SOCKLEN_T fromlen = sizeof(from);
9bbd7ba3
GRG
958 int ret;
959
9bbd7ba3
GRG
960 ret = recvfrom(socket->m_fd, buffer, size, 0, &from, &fromlen);
961
962 if (ret == SOCKET_ERROR)
75d684d9 963 return SOCKET_ERROR;
9bbd7ba3
GRG
964
965 /* Translate a system address into a GSocket address */
966 if (!socket->m_peer)
967 {
968 socket->m_peer = GAddress_new();
969 if (!socket->m_peer)
970 {
971 socket->m_error = GSOCK_MEMERR;
972 return -1;
973 }
974 }
975 if (_GAddress_translate_from(socket->m_peer, &from, fromlen) != GSOCK_NOERROR)
976 {
cb421e53
GRG
977 socket->m_error = GSOCK_MEMERR;
978 GAddress_destroy(socket->m_peer);
9bbd7ba3
GRG
979 return -1;
980 }
981
982 return ret;
983}
984
985int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size)
986{
75d684d9 987 return send(socket->m_fd, buffer, size, 0);
9bbd7ba3
GRG
988}
989
990int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size)
991{
992 struct sockaddr *addr;
993 int len, ret;
994
995 if (!socket->m_peer)
996 {
997 socket->m_error = GSOCK_INVADDR;
998 return -1;
999 }
1000
1001 if (!_GAddress_translate_to(socket->m_peer, &addr, &len))
1002 {
1003 socket->m_error = GSOCK_MEMERR;
1004 return -1;
1005 }
1006
1007 ret = sendto(socket->m_fd, buffer, size, 0, addr, len);
1008
1009 /* Frees memory allocated by _GAddress_translate_to */
1010 free(addr);
1011
9bbd7ba3
GRG
1012 return ret;
1013}
1014
1015
1016/*
1017 * -------------------------------------------------------------------------
1018 * GAddress
1019 * -------------------------------------------------------------------------
1020 */
1021
1022/* CHECK_ADDRESS verifies that the current family is either GSOCK_NOFAMILY
1023 * or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it initalizes address
1024 * to be a GSOCK_*family*. In other cases, it returns GSOCK_INVADDR.
1025 */
1026#define CHECK_ADDRESS(address, family, retval) \
1027{ \
1028 if (address->m_family == GSOCK_NOFAMILY) \
1029 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1030 return address->m_error; \
1031 if (address->m_family != GSOCK_##family) \
1032 { \
1033 address->m_error = GSOCK_INVADDR; \
1034 return retval; \
1035 } \
1036}
1037
1038GAddress *GAddress_new()
1039{
1040 GAddress *address;
1041
1042 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1043 return NULL;
1044
1045 address->m_family = GSOCK_NOFAMILY;
1046 address->m_addr = NULL;
1047 address->m_len = 0;
1048
1049 return address;
1050}
1051
1052GAddress *GAddress_copy(GAddress *address)
1053{
1054 GAddress *addr2;
1055
1056 assert(address != NULL);
1057
1058 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1059 return NULL;
1060
1061 memcpy(addr2, address, sizeof(GAddress));
1062
1063 if (address->m_addr)
1064 {
1065 addr2->m_addr = (struct sockaddr *) malloc(addr2->m_len);
1066 if (addr2->m_addr == NULL)
1067 {
1068 free(addr2);
1069 return NULL;
1070 }
1071 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
1072 }
1073
1074 return addr2;
1075}
1076
1077void GAddress_destroy(GAddress *address)
1078{
1079 assert(address != NULL);
1080
1081 free(address);
1082}
1083
1084void GAddress_SetFamily(GAddress *address, GAddressType type)
1085{
1086 assert(address != NULL);
1087
1088 address->m_family = type;
1089}
1090
1091GAddressType GAddress_GetFamily(GAddress *address)
1092{
1093 assert(address != NULL);
1094
1095 return address->m_family;
1096}
1097
1098GSocketError _GAddress_translate_from(GAddress *address,
1099 struct sockaddr *addr, int len)
1100{
1101 address->m_realfamily = addr->sa_family;
1102 switch (addr->sa_family)
1103 {
1104 case AF_INET:
1105 address->m_family = GSOCK_INET;
1106 break;
1107 case AF_UNIX:
1108 address->m_family = GSOCK_UNIX;
1109 break;
1110#ifdef AF_INET6
1111 case AF_INET6:
1112 address->m_family = GSOCK_INET6;
1113 break;
1114#endif
1115 default:
1116 {
1117 address->m_error = GSOCK_INVOP;
1118 return GSOCK_INVOP;
1119 }
1120 }
1121
1122 if (address->m_addr)
1123 free(address->m_addr);
1124
1125 address->m_len = len;
1126 address->m_addr = (struct sockaddr *) malloc(len);
1127
1128 if (address->m_addr == NULL)
1129 {
1130 address->m_error = GSOCK_MEMERR;
1131 return GSOCK_MEMERR;
1132 }
1133 memcpy(address->m_addr, addr, len);
1134
1135 return GSOCK_NOERROR;
1136}
1137
1138GSocketError _GAddress_translate_to(GAddress *address,
1139 struct sockaddr **addr, int *len)
1140{
1141 if (!address->m_addr)
1142 {
1143 address->m_error = GSOCK_INVADDR;
1144 return GSOCK_INVADDR;
1145 }
1146
1147 *len = address->m_len;
1148 *addr = (struct sockaddr *) malloc(address->m_len);
1149 if (*addr == NULL)
1150 {
1151 address->m_error = GSOCK_MEMERR;
1152 return GSOCK_MEMERR;
1153 }
1154
1155 memcpy(*addr, address->m_addr, address->m_len);
1156 return GSOCK_NOERROR;
1157}
1158
1159/*
1160 * -------------------------------------------------------------------------
1161 * Internet address family
1162 * -------------------------------------------------------------------------
1163 */
1164
1165GSocketError _GAddress_Init_INET(GAddress *address)
1166{
e22da5d6 1167 address->m_len = sizeof(struct sockaddr_in);
9bbd7ba3
GRG
1168 address->m_addr = (struct sockaddr *) malloc(address->m_len);
1169 if (address->m_addr == NULL)
1170 {
1171 address->m_error = GSOCK_MEMERR;
1172 return GSOCK_MEMERR;
1173 }
1174
9bbd7ba3
GRG
1175 address->m_family = GSOCK_INET;
1176 address->m_realfamily = PF_INET;
1177 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
06a0865f 1178 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_NONE;
9bbd7ba3
GRG
1179
1180 return GSOCK_NOERROR;
1181}
1182
1183GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
1184{
1185 struct hostent *he;
1186 struct in_addr *addr;
1187
1188 assert(address != NULL);
1189
1190 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1191
1192 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1193
1194 addr->s_addr = inet_addr(hostname);
b661e675 1195
9bbd7ba3
GRG
1196 /* If it is a numeric host name, convert it now */
1197 if (addr->s_addr == INADDR_NONE)
1198 {
1199 struct in_addr *array_addr;
1200
1201 /* It is a real name, we solve it */
1202 if ((he = gethostbyname(hostname)) == NULL)
1203 {
1204 address->m_error = GSOCK_NOHOST;
1205 return GSOCK_NOHOST;
1206 }
1207 array_addr = (struct in_addr *) *(he->h_addr_list);
1208 addr->s_addr = array_addr[0].s_addr;
1209 }
1210 return GSOCK_NOERROR;
1211}
1212
1213GSocketError GAddress_INET_SetHostAddress(GAddress *address,
1214 unsigned long hostaddr)
1215{
1216 struct in_addr *addr;
1217
1218 assert(address != NULL);
1219
1220 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1221
1222 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1223 addr->s_addr = hostaddr;
1224
1225 return GSOCK_NOERROR;
1226}
1227
1228GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1229 const char *protocol)
1230{
1231 struct servent *se;
1232 struct sockaddr_in *addr;
1233
1234 assert(address != NULL);
1235 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1236
1237 if (!port)
1238 {
1239 address->m_error = GSOCK_INVPORT;
1240 return GSOCK_INVOP;
1241 }
b661e675 1242
9bbd7ba3
GRG
1243 se = getservbyname(port, protocol);
1244 if (!se)
1245 {
1246 if (isdigit(port[0]))
1247 {
1248 int port_int;
1249
1250 port_int = atoi(port);
1251 addr = (struct sockaddr_in *)address->m_addr;
aa3981f2 1252 addr->sin_port = htons((u_short) port_int);
9bbd7ba3
GRG
1253 return GSOCK_NOERROR;
1254 }
1255
1256 address->m_error = GSOCK_INVPORT;
1257 return GSOCK_INVPORT;
1258 }
1259
1260 addr = (struct sockaddr_in *)address->m_addr;
1261 addr->sin_port = se->s_port;
1262
1263 return GSOCK_NOERROR;
1264}
1265
1266GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1267{
1268 struct sockaddr_in *addr;
1269
1270 assert(address != NULL);
1271 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
b661e675 1272
9bbd7ba3
GRG
1273 addr = (struct sockaddr_in *)address->m_addr;
1274 addr->sin_port = htons(port);
1275
1276 return GSOCK_NOERROR;
1277}
1278
1279GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1280{
1281 struct hostent *he;
1282 char *addr_buf;
1283 struct sockaddr_in *addr;
1284
b661e675 1285 assert(address != NULL);
9bbd7ba3
GRG
1286 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1287
1288 addr = (struct sockaddr_in *)address->m_addr;
1289 addr_buf = (char *)&(addr->sin_addr);
1290
1291 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
1292 if (he == NULL)
1293 {
1294 address->m_error = GSOCK_NOHOST;
1295 return GSOCK_NOHOST;
1296 }
1297
1298 strncpy(hostname, he->h_name, sbuf);
1299
1300 return GSOCK_NOERROR;
1301}
1302
1303unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1304{
1305 struct sockaddr_in *addr;
1306
b661e675
RD
1307 assert(address != NULL);
1308 CHECK_ADDRESS(address, INET, 0);
9bbd7ba3
GRG
1309
1310 addr = (struct sockaddr_in *)address->m_addr;
1311
1312 return addr->sin_addr.s_addr;
1313}
1314
1315unsigned short GAddress_INET_GetPort(GAddress *address)
1316{
1317 struct sockaddr_in *addr;
1318
b661e675
RD
1319 assert(address != NULL);
1320 CHECK_ADDRESS(address, INET, 0);
9bbd7ba3
GRG
1321
1322 addr = (struct sockaddr_in *)address->m_addr;
1323 return ntohs(addr->sin_port);
1324}
1325
1326/*
1327 * -------------------------------------------------------------------------
1328 * Unix address family
1329 * -------------------------------------------------------------------------
1330 */
1331
1332GSocketError _GAddress_Init_UNIX(GAddress *address)
1333{
1334 assert (address != NULL);
1335 address->m_error = GSOCK_INVADDR;
1336 return GSOCK_INVADDR;
1337}
1338
1339GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
1340{
1341 assert (address != NULL);
1342 address->m_error = GSOCK_INVADDR;
1343 return GSOCK_INVADDR;
1344}
1345
1346GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf)
1347{
1348 assert (address != NULL);
1349 address->m_error = GSOCK_INVADDR;
1350 return GSOCK_INVADDR;
1351}
1352
a497618a 1353#else /* !wxUSE_SOCKETS */
9bbd7ba3 1354
a497618a
VZ
1355/*
1356 * translation unit shouldn't be empty, so include this typedef to make the
1357 * compiler (VC++ 6.0, for example) happy
1358 */
1359typedef (*wxDummy)();
9bbd7ba3 1360
a497618a 1361#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */
9bbd7ba3
GRG
1362
1363/* Diferencias con la version Unix:
1364 * - El descriptor es SOCKET y no int
1365 * - Constantes -1 pasan a INVALID_SOCKET
1366 * - Errores en muchas funciones pasan de -1 o <0 a SOCKET_ERROR
1367 * - ioctl y close pasan a ioctlsocket y closesocket
1368 * - inet_addr en lugar de inet_aton
1369 * - Codigo de inicializacion y terminacion para inicializar y
1370 * terminar WinSocket y para la ventana interna.
75d684d9
GRG
1371 * - SetTimeout, SetNonBlocking y la implementacion de los
1372 * timeouts eran bastante diferentes, pero ahora se han
1373 * hecho en la version Unix igual que en esta.
9bbd7ba3 1374 */