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