2 * WINGs WMConnection function library
4 * Copyright (c) 1999-2000 Dan Pascu
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * - decide if we want to support connections with external sockets, else
25 * clean up the structure of the unneeded members.
26 * - decide what to do with all wsyserror() and wwarning() calls.
31 #include "../src/config.h"
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
46 #include <sys/signal.h>
52 /* Some older systems does not define this (linux libc5, maybe others too) */
64 # define INADDR_NONE -1
67 /* Stuff for setting the sockets into non-blocking mode. */
68 /*#ifdef __POSIX_SOURCE
69 # define NONBLOCK_OPT O_NONBLOCK
71 # define NONBLOCK_OPT FNDELAY
74 #define NONBLOCK_OPT O_NONBLOCK
76 #define NETBUF_SIZE 4096
78 #define DEF_TIMEOUT 600 /* 600 seconds == 10 minutes */
84 static Bool SigInitialized
= False
;
86 static unsigned int DefaultTimeout
= DEF_TIMEOUT
;
87 static unsigned int OpenTimeout
= DEF_TIMEOUT
;
91 typedef struct TimeoutData
{
97 typedef struct W_Connection
{
98 int sock
; /* the socket we speak through */
101 WMHandlerID
*read
; /* the input read handler */
102 WMHandlerID
*write
; /* the input write handler */
103 WMHandlerID
*exception
; /* the input exception handler */
106 ConnectionDelegate
*delegate
; /* client delegates */
107 void *clientData
; /* client data */
108 unsigned int uflags
; /* flags for the client */
110 WMArray
*outputQueue
;
113 TimeoutData sendTimeout
;
114 TimeoutData openTimeout
;
116 WMConnectionState state
;
117 WMConnectionTimeoutState timeoutState
;
132 clearOutputQueue(WMConnection
*cPtr
) /*FOLD00*/
135 WMEmptyArray(cPtr
->outputQueue
);
140 openTimeout(void *cdata
) /*FOLD00*/
142 WMConnection
*cPtr
= (WMConnection
*) cdata
;
144 cPtr
->openTimeout
.handler
= NULL
;
145 if (cPtr
->handler
.write
) {
146 WMDeleteInputHandler(cPtr
->handler
.write
);
147 cPtr
->handler
.write
= NULL
;
149 if (cPtr
->state
!= WCConnected
) {
150 cPtr
->state
= WCTimedOut
;
151 cPtr
->timeoutState
= WCTWhileOpening
;
152 if (cPtr
->delegate
&& cPtr
->delegate
->didTimeout
) {
153 (*cPtr
->delegate
->didTimeout
)(cPtr
->delegate
, cPtr
);
155 WMCloseConnection(cPtr
);
156 cPtr
->state
= WCTimedOut
; /* the above set state to WCClosed */
163 sendTimeout(void *cdata
) /*FOLD00*/
165 WMConnection
*cPtr
= (WMConnection
*) cdata
;
167 cPtr
->sendTimeout
.handler
= NULL
;
168 if (cPtr
->handler
.write
) {
169 WMDeleteInputHandler(cPtr
->handler
.write
);
170 cPtr
->handler
.write
= NULL
;
172 if (WMGetArrayItemCount(cPtr
->outputQueue
)>0) {
173 clearOutputQueue(cPtr
);
174 cPtr
->state
= WCTimedOut
;
175 cPtr
->timeoutState
= WCTWhileSending
;
176 if (cPtr
->delegate
&& cPtr
->delegate
->didTimeout
) {
177 (*cPtr
->delegate
->didTimeout
)(cPtr
->delegate
, cPtr
);
179 WMCloseConnection(cPtr
);
180 cPtr
->state
= WCTimedOut
; /* the above set state to WCClosed */
187 inputHandler(int fd
, int mask
, void *clientData
) /*FOLD00*/
189 WMConnection
*cPtr
= (WMConnection
*)clientData
;
191 if (cPtr
->state
==WCClosed
|| cPtr
->state
==WCDied
)
194 if ((mask
& WIWriteMask
)) {
195 if (cPtr
->state
== WCInProgress
) {
198 int len
= sizeof(result
);
200 if (getsockopt(cPtr
->sock
, SOL_SOCKET
, SO_ERROR
,
201 (void*)&result
, &len
) == 0 && result
!= 0) {
202 cPtr
->state
= WCFailed
;
203 WCErrorCode
= result
;
205 /* should call wsyserrorwithcode(result, ...) here? */
207 cPtr
->state
= WCConnected
;
211 if (cPtr
->handler
.write
) {
212 WMDeleteInputHandler(cPtr
->handler
.write
);
213 cPtr
->handler
.write
= NULL
;
216 if (cPtr
->openTimeout
.handler
) {
217 WMDeleteTimerHandler(cPtr
->openTimeout
.handler
);
218 cPtr
->openTimeout
.handler
= NULL
;
221 if (cPtr
->delegate
&& cPtr
->delegate
->didInitialize
)
222 (*cPtr
->delegate
->didInitialize
)(cPtr
->delegate
, cPtr
);
224 /* we use failed and not cPtr->state here, because cPtr may be
225 * destroyed by the delegate called above if the connection failed
229 } else if (cPtr
->state
== WCConnected
) {
230 WMFlushConnection(cPtr
);
237 /* if the connection died, may get destroyed in the delegate, so retain */
240 if ((mask
& WIReadMask
) && cPtr
->delegate
->didReceiveInput
)
241 (*cPtr
->delegate
->didReceiveInput
)(cPtr
->delegate
, cPtr
);
243 if ((mask
& WIExceptMask
) && cPtr
->delegate
->didCatchException
)
244 (*cPtr
->delegate
->didCatchException
)(cPtr
->delegate
, cPtr
);
251 setSocketNonBlocking(int sock
, Bool flag
) /*FOLD00*/
256 state
= fcntl(sock
, F_GETFL
, 0);
259 /*wsyserror("Failed to get socket flags with fcntl."); should we do this? -Dan*/
263 isNonBlock
= (state
& NONBLOCK_OPT
) != 0;
268 state
|= NONBLOCK_OPT
;
272 state
&= ~NONBLOCK_OPT
;
275 if (fcntl(sock
, F_SETFL
, state
) < 0) {
276 /*wsyserror("Failed to set socket flags with fcntl."); should we do this? -Dan */
285 setConnectionAddress(WMConnection
*cPtr
, struct sockaddr_in
*socketaddr
) /*FOLD00*/
287 wassertr(cPtr
->address
==NULL
);
289 cPtr
->address
= wstrdup(inet_ntoa(socketaddr
->sin_addr
));
290 cPtr
->service
= wmalloc(16);
291 sprintf(cPtr
->service
, "%hu", ntohs(socketaddr
->sin_port
));
292 cPtr
->protocol
= wstrdup("tcp");
296 static struct sockaddr_in
*
297 getSocketAddress(char* name
, char* service
, char* protocol
) /*FOLD00*/
299 static struct sockaddr_in socketaddr
;
302 if (!protocol
|| protocol
[0]=='\0')
305 memset(&socketaddr
, 0, sizeof(struct sockaddr_in
));
306 socketaddr
.sin_family
= AF_INET
;
309 * If we were given a hostname, we use any address for that host.
310 * Otherwise we expect the given name to be an address unless it is
311 * NULL (any address).
313 if (name
&& name
[0]!='\0') {
314 WMHost
*host
= WMGetHostWithName(name
);
317 return NULL
; /* name is not a hostname nor a number and dot adr */
319 name
= WMGetHostAddress(host
);
320 #ifndef HAVE_INET_ATON
321 if ((socketaddr
.sin_addr
.s_addr
= inet_addr(name
)) == INADDR_NONE
) {
323 if (inet_aton(name
, &socketaddr
.sin_addr
) == 0) {
330 socketaddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
333 if (!service
|| service
[0]=='\0') {
334 socketaddr
.sin_port
= 0;
335 } else if ((sp
= getservbyname(service
, protocol
))==0) {
339 portNumber
= strtoul(service
, &endptr
, 10);
341 if (service
[0]!='\0' && *endptr
=='\0' && portNumber
<65536) {
342 socketaddr
.sin_port
= htons(portNumber
);
347 socketaddr
.sin_port
= sp
->s_port
;
355 createConnectionWithSocket(int sock
, Bool closeOnRelease
) /*FOLD00*/
358 struct sigaction sig_action
;
360 cPtr
= wmalloc(sizeof(WMConnection
));
362 memset(cPtr
, 0, sizeof(WMConnection
));
364 fcntl(sock
, F_SETFD
, FD_CLOEXEC
); /* by default close on exec */
367 cPtr
->openTimeout
.timeout
= OpenTimeout
;
368 cPtr
->openTimeout
.handler
= NULL
;
369 cPtr
->sendTimeout
.timeout
= DefaultTimeout
;
370 cPtr
->sendTimeout
.handler
= NULL
;
371 cPtr
->closeOnRelease
= closeOnRelease
;
373 WMCreateArrayWithDestructor(16, (WMFreeDataProc
*)WMReleaseData
);
374 cPtr
->state
= WCNotConnected
;
375 cPtr
->timeoutState
= WCTNone
;
377 /* ignore dead pipe */
378 if (!SigInitialized
) {
379 sig_action
.sa_handler
= SIG_IGN
;
380 sig_action
.sa_flags
= SA_RESTART
;
381 sigaction(SIGPIPE
, &sig_action
, NULL
);
382 SigInitialized
= True
;
391 WMCreateConnectionWithSocket(int sock
, Bool closeOnRelease
) /*FOLD00*/
394 struct sockaddr_in clientname
;
397 cPtr
= createConnectionWithSocket(sock
, closeOnRelease
);
398 cPtr
->wasNonBlocking
= WMIsConnectionNonBlocking(cPtr
);
399 cPtr
->isNonBlocking
= cPtr
->wasNonBlocking
;
401 /* some way to find out if it is connected, and binded. can't find
402 if it listens though!!!
405 size
= sizeof(clientname
);
406 n
= getpeername(sock
, (struct sockaddr
*) &clientname
, &size
);
408 /* Since we have a peer, it means we are connected */
409 cPtr
->state
= WCConnected
;
411 size
= sizeof(clientname
);
412 n
= getsockname(sock
, (struct sockaddr
*) &clientname
, &size
);
414 /* We don't have a peer, but we are binded to an address.
415 * Assume we are listening on it (we don't know that for sure!)
417 cPtr
->state
= WCListening
;
419 cPtr
->state
= WCNotConnected
;
429 * host is the name on which we want to listen for incoming connections,
430 * and it must be a name of this host, or NULL if we want to listen
431 * on any incoming address.
432 * service is either a service name as present in /etc/services, or the port
433 * number we want to listen on. If NULL, a random port between
434 * 1024 and 65535 will be assigned to us.
435 * protocol is one of "tcp" or "udp". If NULL, "tcp" will be used by default.
436 * currently only "tcp" is supported.
439 WMCreateConnectionAsServerAtAddress(char *host
, char *service
, char *protocol
) /*FOLD00*/
442 struct sockaddr_in
*socketaddr
;
445 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
447 wwarning("Bad address-service-protocol combination");
451 /* Create the actual socket */
452 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
455 wsyserror("Unable to create socket");
460 * Set socket options. We try to make the port reusable and have it
461 * close as fast as possible without waiting in unnecessary wait states
465 setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, (void *)&on
, sizeof(on
));
467 if (bind(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
469 wsyserror("Unable to bind to address '%s:%hu'",
470 inet_ntoa(socketaddr
->sin_addr
),
471 ntohs(socketaddr
->sin_port
));
476 if (listen(sock
, 10) < 0) {
478 wsyserror("Unable to listen on port '%hu'",
479 ntohs(socketaddr
->sin_port
));
484 /* Find out what is the address/service/protocol we get */
485 /* In case some of address/service/protocol were NULL */
486 size
= sizeof(*socketaddr
);
487 if (getsockname(sock
, (struct sockaddr
*)socketaddr
, &size
) < 0) {
489 wsyserror("Unable to get socket address");
494 cPtr
= createConnectionWithSocket(sock
, True
);
495 cPtr
->state
= WCListening
;
496 WMSetConnectionNonBlocking(cPtr
, True
);
498 setConnectionAddress(cPtr
, socketaddr
);
505 WMCreateConnectionToAddress(char *host
, char *service
, char *protocol
) /*FOLD00*/
508 struct sockaddr_in
*socketaddr
;
511 if (service
==NULL
|| service
[0]=='\0') {
513 wwarning("Bad argument - service is not specified");
517 if (host
==NULL
|| host
[0]=='\0')
520 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
522 wwarning("Bad address-service-protocol combination");
526 /* Create the actual socket */
527 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
530 wsyserror("Unable to create socket");
533 /* make socket blocking while we connect. */
534 setSocketNonBlocking(sock
, False
);
535 if (connect(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
537 wsyserror("Unable to make connection to address '%s:%hu'",
538 inet_ntoa(socketaddr
->sin_addr
),
539 ntohs(socketaddr
->sin_port
));
544 cPtr
= createConnectionWithSocket(sock
, True
);
545 cPtr
->state
= WCConnected
;
546 WMSetConnectionNonBlocking(cPtr
, True
);
547 setConnectionAddress(cPtr
, socketaddr
);
554 WMCreateConnectionToAddressAndNotify(char *host
, char *service
, char *protocol
) /*FOLD00*/
557 struct sockaddr_in
*socketaddr
;
561 if (service
==NULL
|| service
[0]=='\0') {
563 wwarning("Bad argument - service is not specified");
567 if (host
==NULL
|| host
[0]=='\0')
570 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
572 wwarning("Bad address-service-protocol combination");
576 /* Create the actual socket */
577 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
580 wsyserror("Unable to create socket");
583 isNonBlocking
= setSocketNonBlocking(sock
, True
);
584 if (connect(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
585 if (errno
!=EINPROGRESS
) {
587 wsyserror("Unable to make connection to address '%s:%hu'",
588 inet_ntoa(socketaddr
->sin_addr
),
589 ntohs(socketaddr
->sin_port
));
595 cPtr
= createConnectionWithSocket(sock
, True
);
596 cPtr
->state
= WCInProgress
;
597 cPtr
->isNonBlocking
= isNonBlocking
;
599 cPtr
->handler
.write
= WMAddInputHandler(cPtr
->sock
, WIWriteMask
,
602 cPtr
->openTimeout
.handler
=
603 WMAddTimerHandler(cPtr
->openTimeout
.timeout
*1000, openTimeout
, cPtr
);
605 setConnectionAddress(cPtr
, socketaddr
);
612 removeAllHandlers(WMConnection
*cPtr
) /*FOLD00*/
614 if (cPtr
->handler
.read
)
615 WMDeleteInputHandler(cPtr
->handler
.read
);
616 if (cPtr
->handler
.write
)
617 WMDeleteInputHandler(cPtr
->handler
.write
);
618 if (cPtr
->handler
.exception
)
619 WMDeleteInputHandler(cPtr
->handler
.exception
);
620 if (cPtr
->openTimeout
.handler
)
621 WMDeleteTimerHandler(cPtr
->openTimeout
.handler
);
622 if (cPtr
->sendTimeout
.handler
)
623 WMDeleteTimerHandler(cPtr
->sendTimeout
.handler
);
625 cPtr
->handler
.read
= NULL
;
626 cPtr
->handler
.write
= NULL
;
627 cPtr
->handler
.exception
= NULL
;
628 cPtr
->openTimeout
.handler
= NULL
;
629 cPtr
->sendTimeout
.handler
= NULL
;
634 WMDestroyConnection(WMConnection
*cPtr
) /*FOLD00*/
636 if (cPtr
->closeOnRelease
&& cPtr
->sock
>=0) {
637 shutdown(cPtr
->sock
, SHUT_RDWR
);
641 removeAllHandlers(cPtr
);
642 WMFreeArray(cPtr
->outputQueue
); /* will also free the items with the destructor */
645 wfree(cPtr
->address
);
646 wfree(cPtr
->service
);
647 wfree(cPtr
->protocol
);
655 WMCloseConnection(WMConnection
*cPtr
) /*FOLD00*/
658 shutdown(cPtr
->sock
, SHUT_RDWR
);
663 removeAllHandlers(cPtr
);
664 clearOutputQueue(cPtr
);
666 cPtr
->state
= WCClosed
;
671 WMAcceptConnection(WMConnection
*listener
) /*FOLD00*/
673 struct sockaddr_in clientname
;
676 WMConnection
*newConnection
;
679 wassertrv(listener
&& listener
->state
==WCListening
, NULL
);
681 size
= sizeof(clientname
);
682 newSock
= accept(listener
->sock
, (struct sockaddr
*) &clientname
, &size
);
684 if (errno
!=EAGAIN
&& errno
!=EWOULDBLOCK
) {
686 wsyserror("Could not accept connection");
693 newConnection
= createConnectionWithSocket(newSock
, True
);
694 WMSetConnectionNonBlocking(newConnection
, True
);
695 newConnection
->state
= WCConnected
;
696 setConnectionAddress(newConnection
, &clientname
);
698 return newConnection
;
703 WMGetConnectionAddress(WMConnection
*cPtr
) /*FOLD00*/
705 return cPtr
->address
;
710 WMGetConnectionService(WMConnection
*cPtr
) /*FOLD00*/
712 return cPtr
->service
;
717 WMGetConnectionProtocol(WMConnection
*cPtr
) /*FOLD00*/
719 return cPtr
->protocol
;
724 WMGetConnectionSocket(WMConnection
*cPtr
) /*FOLD00*/
731 WMGetConnectionState(WMConnection
*cPtr
) /*FOLD00*/
737 WMConnectionTimeoutState
738 WMGetConnectionTimeoutState(WMConnection
*cPtr
) /*FOLD00*/
740 return cPtr
->timeoutState
;
745 WMEnqueueConnectionData(WMConnection
*cPtr
, WMData
*data
) /*FOLD00*/
747 wassertrv(cPtr
->state
!=WCNotConnected
&& cPtr
->state
!=WCListening
, False
);
748 wassertrv(cPtr
->state
!=WCInProgress
&& cPtr
->state
!=WCFailed
, False
);
750 if (cPtr
->state
!=WCConnected
)
753 WMAddToArray(cPtr
->outputQueue
, WMRetainData(data
));
759 WMSendConnectionData(WMConnection
*cPtr
, WMData
*data
) /*FOLD00*/
761 int bytes
, pos
, len
, totalTransfer
;
762 TimeoutData
*tPtr
= &cPtr
->sendTimeout
;
763 const unsigned char *dataBytes
;
765 wassertrv(cPtr
->state
!=WCNotConnected
&& cPtr
->state
!=WCListening
, -1);
766 wassertrv(cPtr
->state
!=WCInProgress
&& cPtr
->state
!=WCFailed
, -1);
768 if (cPtr
->state
!=WCConnected
)
771 /* If we have no data just flush the queue, else try to send data */
772 if (data
&& WMGetDataLength(data
)>0) {
773 WMAddToArray(cPtr
->outputQueue
, WMRetainData(data
));
774 /* If there already was something in queue, and also a write input
775 * handler is established, it means we were unable to send, so
776 * return and let the write handler notify us when we can send.
778 if (WMGetArrayItemCount(cPtr
->outputQueue
)>1 && cPtr
->handler
.write
)
784 while (WMGetArrayItemCount(cPtr
->outputQueue
) > 0) {
785 data
= WMGetFromArray(cPtr
->outputQueue
, 0);
786 dataBytes
= (const unsigned char *)WMDataBytes(data
);
787 len
= WMGetDataLength(data
);
788 pos
= cPtr
->bufPos
; /* where we're left last time */
791 bytes
= write(cPtr
->sock
, dataBytes
+pos
, len
- pos
);
797 /* save the position where we're left and add a timeout */
799 if (!tPtr
->handler
) {
800 tPtr
->handler
= WMAddTimerHandler(tPtr
->timeout
*1000,
803 if (!cPtr
->handler
.write
) {
804 cPtr
->handler
.write
=
805 WMAddInputHandler(cPtr
->sock
, WIWriteMask
,
808 return totalTransfer
;
811 cPtr
->state
= WCDied
;
812 removeAllHandlers(cPtr
);
813 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
814 (*cPtr
->delegate
->didDie
)(cPtr
->delegate
, cPtr
);
819 totalTransfer
+= bytes
;
821 WMDeleteFromArray(cPtr
->outputQueue
, 0);
824 WMDeleteTimerHandler(tPtr
->handler
);
825 tPtr
->handler
= NULL
;
827 if (cPtr
->handler
.write
) {
828 WMDeleteInputHandler(cPtr
->handler
.write
);
829 cPtr
->handler
.write
= NULL
;
833 return totalTransfer
;
838 * WMGetConnectionAvailableData(connection):
840 * will return a WMData structure containing the available data on the
841 * specified connection. If connection is non-blocking (default) and no data
842 * is available when this function is called, an empty WMData is returned.
844 * If an error occurs while reading or the other side closed connection,
845 * it will return NULL.
846 * Also trying to read from an already died or closed connection is
847 * considered to be an error condition, and will return NULL.
850 WMGetConnectionAvailableData(WMConnection
*cPtr
) /*FOLD00*/
852 char buffer
[NETBUF_SIZE
];
856 wassertrv(cPtr
->state
!=WCNotConnected
&& cPtr
->state
!=WCListening
, NULL
);
857 wassertrv(cPtr
->state
!=WCInProgress
&& cPtr
->state
!=WCFailed
, NULL
);
859 if (cPtr
->state
!=WCConnected
)
865 nbytes
= read(cPtr
->sock
, buffer
, NETBUF_SIZE
);
871 aData
= WMCreateDataWithCapacity(0);
875 cPtr
->state
= WCDied
;
876 removeAllHandlers(cPtr
);
877 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
878 (*cPtr
->delegate
->didDie
)(cPtr
->delegate
, cPtr
);
881 } else if (nbytes
==0) { /* the other side has closed connection */
882 cPtr
->state
= WCClosed
;
883 removeAllHandlers(cPtr
);
884 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
885 (*cPtr
->delegate
->didDie
)(cPtr
->delegate
, cPtr
);
887 aData
= WMCreateDataWithBytes(buffer
, nbytes
);
895 WMSetConnectionDelegate(WMConnection
*cPtr
, ConnectionDelegate
*delegate
) /*FOLD00*/
897 wassertr(cPtr
->sock
>= 0);
898 /* Don't try to set the delegate multiple times */
899 wassertr(cPtr
->delegate
== NULL
);
901 cPtr
->delegate
= delegate
;
902 if (delegate
&& delegate
->didReceiveInput
&& !cPtr
->handler
.read
)
903 cPtr
->handler
.read
= WMAddInputHandler(cPtr
->sock
, WIReadMask
,
905 if (delegate
&& delegate
->didCatchException
&& !cPtr
->handler
.exception
)
906 cPtr
->handler
.exception
= WMAddInputHandler(cPtr
->sock
, WIExceptMask
,
913 WMIsConnectionNonBlocking(WMConnection
*cPtr
) /*FOLD00*/
918 state
= fcntl(cPtr
->sock
, F_GETFL
, 0);
921 /*wsyserror("Failed to get socket flags with fcntl.");*/
922 /* If we can't use fcntl on socket, this probably also means we could
923 * not use fcntl to set non-blocking mode, and since a socket defaults
924 * to blocking when created, return False as the best assumption */
928 return ((state
& NONBLOCK_OPT
)!=0);
930 return cPtr
->isNonBlocking
;
937 WMSetConnectionNonBlocking(WMConnection
*cPtr
, Bool flag
) /*FOLD00*/
939 wassertrv(cPtr
!=NULL
&& cPtr
->sock
>=0, False
);
941 if (cPtr
->isNonBlocking
== flag
)
944 if (setSocketNonBlocking(cPtr
->sock
, flag
)==True
) {
945 cPtr
->isNonBlocking
= flag
;
954 WMSetConnectionCloseOnExec(WMConnection
*cPtr
, Bool flag
)
956 wassertrv(cPtr
!=NULL
&& cPtr
->sock
>=0, False
);
958 if (fcntl(cPtr
->sock
, F_SETFD
, (flag
? FD_CLOEXEC
: 0)) < 0) {
967 WMGetConnectionClientData(WMConnection
*cPtr
) /*FOLD00*/
969 return cPtr
->clientData
;
974 WMSetConnectionClientData(WMConnection
*cPtr
, void *data
) /*FOLD00*/
976 cPtr
->clientData
= data
;
981 WMGetConnectionFlags(WMConnection
*cPtr
) /*FOLD00*/
988 WMSetConnectionFlags(WMConnection
*cPtr
, unsigned int flags
) /*FOLD00*/
990 cPtr
->uflags
= flags
;
995 WMGetConnectionUnsentData(WMConnection
*cPtr
)
997 return cPtr
->outputQueue
;
1002 WMSetConnectionDefaultTimeout(unsigned int timeout
) /*FOLD00*/
1005 DefaultTimeout
= DEF_TIMEOUT
;
1007 DefaultTimeout
= timeout
;
1013 WMSetConnectionOpenTimeout(unsigned int timeout
) /*FOLD00*/
1016 OpenTimeout
= DefaultTimeout
;
1018 OpenTimeout
= timeout
;
1024 WMSetConnectionSendTimeout(WMConnection
*cPtr
, unsigned int timeout
) /*FOLD00*/
1027 cPtr
->sendTimeout
.timeout
= DefaultTimeout
;
1029 cPtr
->sendTimeout
.timeout
= timeout
;