2 * WINGs WMConnection function library
4 * Copyright (c) 1999-2003 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.
23 * - decide if we want to support connections with external sockets, else
24 * clean up the structure of the unneeded members.
25 * - decide what to do with all wwarning() calls that are still there.
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
44 #include <sys/signal.h>
49 /* Some older systems does not define this (linux libc5, maybe others too) */
61 # define INADDR_NONE -1
64 /* Stuff for setting the sockets into non-blocking mode. */
67 # define NONBLOCK_OPT O_NONBLOCK
69 # define NONBLOCK_OPT FNDELAY
73 #define NONBLOCK_OPT O_NONBLOCK
75 #define NETBUF_SIZE 4096
77 #define DEF_TIMEOUT 600 /* 600 seconds == 10 minutes */
81 static Bool SigInitialized
= False
;
83 static unsigned int DefaultTimeout
= DEF_TIMEOUT
;
84 static unsigned int OpenTimeout
= DEF_TIMEOUT
;
86 typedef struct TimeoutData
{
91 typedef struct W_Connection
{
92 int sock
; /* the socket we speak through */
95 WMHandlerID
*read
; /* the input read handler */
96 WMHandlerID
*write
; /* the input write handler */
97 WMHandlerID
*exception
; /* the input exception handler */
100 ConnectionDelegate
*delegate
; /* client delegates */
101 void *clientData
; /* client data */
102 unsigned int uflags
; /* flags for the client */
104 WMArray
*outputQueue
;
107 TimeoutData sendTimeout
;
108 TimeoutData openTimeout
;
110 WMConnectionState state
;
111 WMConnectionTimeoutState timeoutState
;
118 Bool shutdownOnClose
;
124 static void clearOutputQueue(WMConnection
* cPtr
)
127 WMEmptyArray(cPtr
->outputQueue
);
130 static void openTimeout(void *cdata
)
132 WMConnection
*cPtr
= (WMConnection
*) cdata
;
134 cPtr
->openTimeout
.handler
= NULL
;
135 if (cPtr
->handler
.write
) {
136 WMDeleteInputHandler(cPtr
->handler
.write
);
137 cPtr
->handler
.write
= NULL
;
139 if (cPtr
->state
!= WCConnected
) {
140 cPtr
->state
= WCTimedOut
;
141 cPtr
->timeoutState
= WCTWhileOpening
;
142 if (cPtr
->delegate
&& cPtr
->delegate
->didTimeout
) {
143 (*cPtr
->delegate
->didTimeout
) (cPtr
->delegate
, cPtr
);
145 WMCloseConnection(cPtr
);
146 cPtr
->state
= WCTimedOut
; /* the above set state to WCClosed */
151 static void sendTimeout(void *cdata
)
153 WMConnection
*cPtr
= (WMConnection
*) cdata
;
155 cPtr
->sendTimeout
.handler
= NULL
;
156 if (cPtr
->handler
.write
) {
157 WMDeleteInputHandler(cPtr
->handler
.write
);
158 cPtr
->handler
.write
= NULL
;
160 if (WMGetArrayItemCount(cPtr
->outputQueue
) > 0) {
161 clearOutputQueue(cPtr
);
162 cPtr
->state
= WCTimedOut
;
163 cPtr
->timeoutState
= WCTWhileSending
;
164 /* // should we close it no matter what (after calling the didTimeout
165 // delegate)? -Dan */
166 if (cPtr
->delegate
&& cPtr
->delegate
->didTimeout
) {
167 (*cPtr
->delegate
->didTimeout
) (cPtr
->delegate
, cPtr
);
169 WMCloseConnection(cPtr
);
170 cPtr
->state
= WCTimedOut
; /* the above set state to WCClosed */
175 static void inputHandler(int fd
, int mask
, void *clientData
)
177 WMConnection
*cPtr
= (WMConnection
*) clientData
;
179 if (cPtr
->state
== WCClosed
|| cPtr
->state
== WCDied
)
182 if ((mask
& WIWriteMask
)) {
185 if (cPtr
->state
== WCInProgress
) {
187 socklen_t len
= sizeof(result
);
190 if (getsockopt(cPtr
->sock
, SOL_SOCKET
, SO_ERROR
,
191 (void *)&result
, &len
) == 0 && result
!= 0) {
192 cPtr
->state
= WCFailed
;
193 WCErrorCode
= result
;
195 /* should call wsyserrorwithcode(result, ...) here? */
197 cPtr
->state
= WCConnected
;
201 if (cPtr
->handler
.write
) {
202 WMDeleteInputHandler(cPtr
->handler
.write
);
203 cPtr
->handler
.write
= NULL
;
206 if (cPtr
->openTimeout
.handler
) {
207 WMDeleteTimerHandler(cPtr
->openTimeout
.handler
);
208 cPtr
->openTimeout
.handler
= NULL
;
211 if (cPtr
->delegate
&& cPtr
->delegate
->didInitialize
)
212 (*cPtr
->delegate
->didInitialize
) (cPtr
->delegate
, cPtr
);
214 /* we use failed and not cPtr->state here, because cPtr may be
215 * destroyed by the delegate called above if the connection failed
219 } else if (cPtr
->state
== WCConnected
) {
220 result
= WMFlushConnection(cPtr
);
221 if (result
> 0 && cPtr
->delegate
&& cPtr
->delegate
->canResumeSending
) {
222 (*cPtr
->delegate
->canResumeSending
) (cPtr
->delegate
, cPtr
);
230 /* if the connection died, may get destroyed in the delegate, so retain */
233 if ((mask
& WIReadMask
) && cPtr
->delegate
->didReceiveInput
)
234 (*cPtr
->delegate
->didReceiveInput
) (cPtr
->delegate
, cPtr
);
236 if ((mask
& WIExceptMask
) && cPtr
->delegate
->didCatchException
)
237 (*cPtr
->delegate
->didCatchException
) (cPtr
->delegate
, cPtr
);
242 static Bool
setSocketNonBlocking(int sock
, Bool flag
)
247 state
= fcntl(sock
, F_GETFL
, 0);
250 /* set WCErrorCode here? -Dan */
254 isNonBlock
= (state
& NONBLOCK_OPT
) != 0;
259 state
|= NONBLOCK_OPT
;
263 state
&= ~NONBLOCK_OPT
;
266 if (fcntl(sock
, F_SETFL
, state
) < 0) {
267 /* set WCErrorCode here? -Dan */
274 static void setConnectionAddress(WMConnection
* cPtr
, struct sockaddr_in
*socketaddr
)
276 wassertr(cPtr
->address
== NULL
);
278 cPtr
->address
= wstrdup(inet_ntoa(socketaddr
->sin_addr
));
279 cPtr
->service
= wmalloc(16);
280 sprintf(cPtr
->service
, "%hu", ntohs(socketaddr
->sin_port
));
281 cPtr
->protocol
= wstrdup("tcp");
284 static struct sockaddr_in
*getSocketAddress(char *name
, char *service
, char *protocol
)
286 static struct sockaddr_in socketaddr
;
289 if (!protocol
|| protocol
[0] == 0)
292 memset(&socketaddr
, 0, sizeof(struct sockaddr_in
));
293 socketaddr
.sin_family
= AF_INET
;
296 * If we were given a hostname, we use any address for that host.
297 * Otherwise we expect the given name to be an address unless it is
298 * NULL (any address).
300 if (name
&& name
[0] != 0) {
301 WMHost
*host
= WMGetHostWithName(name
);
304 return NULL
; /* name is not a hostname nor a number and dot adr */
306 name
= WMGetHostAddress(host
);
307 #ifndef HAVE_INET_ATON
308 if ((socketaddr
.sin_addr
.s_addr
= inet_addr(name
)) == INADDR_NONE
) {
310 if (inet_aton(name
, &socketaddr
.sin_addr
) == 0) {
317 socketaddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
320 if (!service
|| service
[0] == 0) {
321 socketaddr
.sin_port
= 0;
322 } else if ((sp
= getservbyname(service
, protocol
)) == 0) {
326 portNumber
= strtoul(service
, &endptr
, 10);
328 if (service
[0] != 0 && *endptr
== 0 && portNumber
< 65536) {
329 socketaddr
.sin_port
= htons(portNumber
);
334 socketaddr
.sin_port
= sp
->s_port
;
340 static void dummyHandler(int signum
)
344 static WMConnection
*createConnectionWithSocket(int sock
, Bool closeOnRelease
)
347 struct sigaction sig_action
;
349 cPtr
= wmalloc(sizeof(WMConnection
));
351 memset(cPtr
, 0, sizeof(WMConnection
));
353 fcntl(sock
, F_SETFD
, FD_CLOEXEC
); /* by default close on exec */
356 cPtr
->openTimeout
.timeout
= OpenTimeout
;
357 cPtr
->openTimeout
.handler
= NULL
;
358 cPtr
->sendTimeout
.timeout
= DefaultTimeout
;
359 cPtr
->sendTimeout
.handler
= NULL
;
360 cPtr
->closeOnRelease
= closeOnRelease
;
361 cPtr
->shutdownOnClose
= 1;
362 cPtr
->outputQueue
= WMCreateArrayWithDestructor(16, (WMFreeDataProc
*) WMReleaseData
);
363 cPtr
->state
= WCNotConnected
;
364 cPtr
->timeoutState
= WCTNone
;
366 /* ignore dead pipe */
367 if (!SigInitialized
) {
368 /* Because POSIX mandates that only signal with handlers are reset
369 * accross an exec*(), we do not want to propagate ignoring SIGPIPEs
370 * to children. Hence the dummy handler. Philippe Troin <phil@fifi.org>
372 sig_action
.sa_handler
= &dummyHandler
;
373 sig_action
.sa_flags
= SA_RESTART
;
374 sigaction(SIGPIPE
, &sig_action
, NULL
);
375 SigInitialized
= True
;
382 WMConnection
*WMCreateConnectionWithSocket(int sock
, Bool closeOnRelease
)
385 struct sockaddr_in clientname
;
389 cPtr
= createConnectionWithSocket(sock
, closeOnRelease
);
390 cPtr
->wasNonBlocking
= WMIsConnectionNonBlocking(cPtr
);
391 cPtr
->isNonBlocking
= cPtr
->wasNonBlocking
;
393 /* some way to find out if it is connected, and binded. can't find
394 if it listens though!!!
397 size
= sizeof(clientname
);
398 n
= getpeername(sock
, (struct sockaddr
*)&clientname
, &size
);
400 /* Since we have a peer, it means we are connected */
401 cPtr
->state
= WCConnected
;
403 size
= sizeof(clientname
);
404 n
= getsockname(sock
, (struct sockaddr
*)&clientname
, &size
);
406 /* We don't have a peer, but we are binded to an address.
407 * Assume we are listening on it (we don't know that for sure!)
409 cPtr
->state
= WCListening
;
411 cPtr
->state
= WCNotConnected
;
420 * host is the name on which we want to listen for incoming connections,
421 * and it must be a name of this host, or NULL if we want to listen
422 * on any incoming address.
423 * service is either a service name as present in /etc/services, or the port
424 * number we want to listen on. If NULL, a random port between
425 * 1024 and 65535 will be assigned to us.
426 * protocol is one of "tcp" or "udp". If NULL, "tcp" will be used by default.
427 * currently only "tcp" is supported.
429 WMConnection
*WMCreateConnectionAsServerAtAddress(char *host
, char *service
, char *protocol
)
432 struct sockaddr_in
*socketaddr
;
438 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
439 wwarning(_("Bad address-service-protocol combination"));
443 /* Create the actual socket */
444 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
451 * Set socket options. We try to make the port reusable and have it
452 * close as fast as possible without waiting in unnecessary wait states
456 setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, (void *)&on
, sizeof(on
));
458 if (bind(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
464 if (listen(sock
, 10) < 0) {
470 /* Find out what is the address/service/protocol we get */
471 /* In case some of address/service/protocol were NULL */
472 size
= sizeof(*socketaddr
);
473 if (getsockname(sock
, (struct sockaddr
*)socketaddr
, &size
) < 0) {
479 cPtr
= createConnectionWithSocket(sock
, True
);
480 cPtr
->state
= WCListening
;
481 WMSetConnectionNonBlocking(cPtr
, True
);
483 setConnectionAddress(cPtr
, socketaddr
);
488 WMConnection
*WMCreateConnectionToAddress(char *host
, char *service
, char *protocol
)
491 struct sockaddr_in
*socketaddr
;
496 wassertrv(service
!= NULL
&& service
[0] != 0, NULL
);
498 if (host
== NULL
|| host
[0] == 0)
501 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
502 wwarning(_("Bad address-service-protocol combination"));
506 /* Create the actual socket */
507 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
512 /* make socket blocking while we connect. */
513 setSocketNonBlocking(sock
, False
);
514 if (connect(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
520 cPtr
= createConnectionWithSocket(sock
, True
);
521 cPtr
->state
= WCConnected
;
522 WMSetConnectionNonBlocking(cPtr
, True
);
523 setConnectionAddress(cPtr
, socketaddr
);
528 WMConnection
*WMCreateConnectionToAddressAndNotify(char *host
, char *service
, char *protocol
)
531 struct sockaddr_in
*socketaddr
;
537 wassertrv(service
!= NULL
&& service
[0] != 0, NULL
);
539 if (host
== NULL
|| host
[0] == 0)
542 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
543 wwarning(_("Bad address-service-protocol combination"));
547 /* Create the actual socket */
548 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
553 isNonBlocking
= setSocketNonBlocking(sock
, True
);
554 if (connect(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
555 if (errno
!= EINPROGRESS
) {
562 cPtr
= createConnectionWithSocket(sock
, True
);
563 cPtr
->state
= WCInProgress
;
564 cPtr
->isNonBlocking
= isNonBlocking
;
566 cPtr
->handler
.write
= WMAddInputHandler(cPtr
->sock
, WIWriteMask
, inputHandler
, cPtr
);
568 cPtr
->openTimeout
.handler
= WMAddTimerHandler(cPtr
->openTimeout
.timeout
* 1000, openTimeout
, cPtr
);
570 setConnectionAddress(cPtr
, socketaddr
);
575 static void removeAllHandlers(WMConnection
* cPtr
)
577 if (cPtr
->handler
.read
)
578 WMDeleteInputHandler(cPtr
->handler
.read
);
579 if (cPtr
->handler
.write
)
580 WMDeleteInputHandler(cPtr
->handler
.write
);
581 if (cPtr
->handler
.exception
)
582 WMDeleteInputHandler(cPtr
->handler
.exception
);
583 if (cPtr
->openTimeout
.handler
)
584 WMDeleteTimerHandler(cPtr
->openTimeout
.handler
);
585 if (cPtr
->sendTimeout
.handler
)
586 WMDeleteTimerHandler(cPtr
->sendTimeout
.handler
);
588 cPtr
->handler
.read
= NULL
;
589 cPtr
->handler
.write
= NULL
;
590 cPtr
->handler
.exception
= NULL
;
591 cPtr
->openTimeout
.handler
= NULL
;
592 cPtr
->sendTimeout
.handler
= NULL
;
595 void WMDestroyConnection(WMConnection
* cPtr
)
597 if (cPtr
->closeOnRelease
&& cPtr
->sock
>= 0) {
598 if (cPtr
->shutdownOnClose
) {
599 shutdown(cPtr
->sock
, SHUT_RDWR
);
604 removeAllHandlers(cPtr
);
605 WMFreeArray(cPtr
->outputQueue
); /* will also free the items with the destructor */
608 wfree(cPtr
->address
);
609 wfree(cPtr
->service
);
610 wfree(cPtr
->protocol
);
616 void WMCloseConnection(WMConnection
* cPtr
)
618 if (cPtr
->sock
>= 0) {
619 if (cPtr
->shutdownOnClose
) {
620 shutdown(cPtr
->sock
, SHUT_RDWR
);
626 removeAllHandlers(cPtr
);
627 clearOutputQueue(cPtr
);
629 cPtr
->state
= WCClosed
;
632 WMConnection
*WMAcceptConnection(WMConnection
* listener
)
634 struct sockaddr_in clientname
;
637 WMConnection
*newConnection
;
640 wassertrv(listener
&& listener
->state
== WCListening
, NULL
);
642 size
= sizeof(clientname
);
643 newSock
= accept(listener
->sock
, (struct sockaddr
*)&clientname
, &size
);
645 WCErrorCode
= ((errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
) ? errno
: 0);
649 newConnection
= createConnectionWithSocket(newSock
, True
);
650 WMSetConnectionNonBlocking(newConnection
, True
);
651 newConnection
->state
= WCConnected
;
652 setConnectionAddress(newConnection
, &clientname
);
654 return newConnection
;
657 char *WMGetConnectionAddress(WMConnection
* cPtr
)
659 return cPtr
->address
;
662 char *WMGetConnectionService(WMConnection
* cPtr
)
664 return cPtr
->service
;
667 char *WMGetConnectionProtocol(WMConnection
* cPtr
)
669 return cPtr
->protocol
;
672 int WMGetConnectionSocket(WMConnection
* cPtr
)
677 WMConnectionState
WMGetConnectionState(WMConnection
* cPtr
)
682 WMConnectionTimeoutState
WMGetConnectionTimeoutState(WMConnection
* cPtr
)
684 return cPtr
->timeoutState
;
687 Bool
WMEnqueueConnectionData(WMConnection
* cPtr
, WMData
* data
)
689 wassertrv(cPtr
->state
!= WCNotConnected
&& cPtr
->state
!= WCListening
, False
);
690 wassertrv(cPtr
->state
!= WCInProgress
&& cPtr
->state
!= WCFailed
, False
);
692 if (cPtr
->state
!= WCConnected
)
695 WMAddToArray(cPtr
->outputQueue
, WMRetainData(data
));
701 * -1 - not connected or connection died while sending
702 * 0 - couldn't send the data (or part of it). data is saved in a queue
703 * and will be sent when possible. after it is sent the canResumeSending
704 * callback will be called.
705 * 1 - data was succesfully sent
707 int WMSendConnectionData(WMConnection
* cPtr
, WMData
* data
)
710 TimeoutData
*tPtr
= &cPtr
->sendTimeout
;
711 const unsigned char *dataBytes
;
713 wassertrv(cPtr
->state
!= WCNotConnected
&& cPtr
->state
!= WCListening
, -1);
714 wassertrv(cPtr
->state
!= WCInProgress
&& cPtr
->state
!= WCFailed
, -1);
716 if (cPtr
->state
!= WCConnected
)
719 /* If we have no data just flush the queue, else try to send data */
720 if (data
&& WMGetDataLength(data
) > 0) {
721 WMAddToArray(cPtr
->outputQueue
, WMRetainData(data
));
722 /* If there already was something in queue, and also a write input
723 * handler is established, it means we were unable to send, so
724 * return and let the write handler notify us when we can send.
726 if (WMGetArrayItemCount(cPtr
->outputQueue
) > 1 && cPtr
->handler
.write
)
730 while (WMGetArrayItemCount(cPtr
->outputQueue
) > 0) {
731 data
= WMGetFromArray(cPtr
->outputQueue
, 0);
732 dataBytes
= (const unsigned char *)WMDataBytes(data
);
733 len
= WMGetDataLength(data
);
734 pos
= cPtr
->bufPos
; /* where we're left last time */
737 bytes
= write(cPtr
->sock
, dataBytes
+ pos
, len
- pos
);
743 /* save the position where we're left and add a timeout */
745 if (!tPtr
->handler
) {
746 tPtr
->handler
= WMAddTimerHandler(tPtr
->timeout
* 1000,
749 if (!cPtr
->handler
.write
) {
750 cPtr
->handler
.write
=
751 WMAddInputHandler(cPtr
->sock
, WIWriteMask
, inputHandler
, cPtr
);
756 cPtr
->state
= WCDied
;
757 removeAllHandlers(cPtr
);
758 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
759 (*cPtr
->delegate
->didDie
) (cPtr
->delegate
, cPtr
);
765 WMDeleteFromArray(cPtr
->outputQueue
, 0);
768 WMDeleteTimerHandler(tPtr
->handler
);
769 tPtr
->handler
= NULL
;
771 /*if (cPtr->handler.write) {
772 WMDeleteInputHandler(cPtr->handler.write);
773 cPtr->handler.write = NULL;
777 if (cPtr
->handler
.write
) {
778 WMDeleteInputHandler(cPtr
->handler
.write
);
779 cPtr
->handler
.write
= NULL
;
786 * WMGetConnectionAvailableData(connection):
788 * will return a WMData structure containing the available data on the
789 * specified connection. If connection is non-blocking (default) and no data
790 * is available when this function is called, an empty WMData is returned.
792 * If an error occurs while reading or the other side closed connection,
793 * it will return NULL.
794 * Also trying to read from an already died or closed connection is
795 * considered to be an error condition, and will return NULL.
797 WMData
*WMGetConnectionAvailableData(WMConnection
* cPtr
)
799 char buffer
[NETBUF_SIZE
];
803 wassertrv(cPtr
->state
!= WCNotConnected
&& cPtr
->state
!= WCListening
, NULL
);
804 wassertrv(cPtr
->state
!= WCInProgress
&& cPtr
->state
!= WCFailed
, NULL
);
806 if (cPtr
->state
!= WCConnected
)
812 nbytes
= read(cPtr
->sock
, buffer
, NETBUF_SIZE
);
818 aData
= WMCreateDataWithCapacity(0);
822 cPtr
->state
= WCDied
;
823 removeAllHandlers(cPtr
);
824 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
825 (*cPtr
->delegate
->didDie
) (cPtr
->delegate
, cPtr
);
828 } else if (nbytes
== 0) { /* the other side has closed connection */
829 cPtr
->state
= WCClosed
;
830 removeAllHandlers(cPtr
);
831 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
832 (*cPtr
->delegate
->didDie
) (cPtr
->delegate
, cPtr
);
834 aData
= WMCreateDataWithBytes(buffer
, nbytes
);
840 void WMSetConnectionDelegate(WMConnection
* cPtr
, ConnectionDelegate
* delegate
)
842 wassertr(cPtr
->sock
>= 0);
843 /* Don't try to set the delegate multiple times */
844 wassertr(cPtr
->delegate
== NULL
);
846 cPtr
->delegate
= delegate
;
847 if (delegate
&& delegate
->didReceiveInput
&& !cPtr
->handler
.read
)
848 cPtr
->handler
.read
= WMAddInputHandler(cPtr
->sock
, WIReadMask
, inputHandler
, cPtr
);
849 if (delegate
&& delegate
->didCatchException
&& !cPtr
->handler
.exception
)
850 cPtr
->handler
.exception
= WMAddInputHandler(cPtr
->sock
, WIExceptMask
, inputHandler
, cPtr
);
854 Bool
WMIsConnectionNonBlocking(WMConnection
* cPtr
)
859 state
= fcntl(cPtr
->sock
, F_GETFL
, 0);
862 /* If we can't use fcntl on socket, this probably also means we could
863 * not use fcntl to set non-blocking mode, and since a socket defaults
864 * to blocking when created, return False as the best assumption */
868 return ((state
& NONBLOCK_OPT
) != 0);
870 return cPtr
->isNonBlocking
;
875 Bool
WMSetConnectionNonBlocking(WMConnection
* cPtr
, Bool flag
)
877 wassertrv(cPtr
!= NULL
&& cPtr
->sock
>= 0, False
);
879 flag
= ((flag
== 0) ? 0 : 1);
881 if (cPtr
->isNonBlocking
== flag
)
884 if (setSocketNonBlocking(cPtr
->sock
, flag
) == True
) {
885 cPtr
->isNonBlocking
= flag
;
892 Bool
WMSetConnectionCloseOnExec(WMConnection
* cPtr
, Bool flag
)
894 wassertrv(cPtr
!= NULL
&& cPtr
->sock
>= 0, False
);
896 if (fcntl(cPtr
->sock
, F_SETFD
, ((flag
== 0) ? 0 : FD_CLOEXEC
)) < 0) {
903 void WMSetConnectionShutdownOnClose(WMConnection
* cPtr
, Bool flag
)
905 cPtr
->shutdownOnClose
= ((flag
== 0) ? 0 : 1);
908 void *WMGetConnectionClientData(WMConnection
* cPtr
)
910 return cPtr
->clientData
;
913 void WMSetConnectionClientData(WMConnection
* cPtr
, void *data
)
915 cPtr
->clientData
= data
;
918 unsigned int WMGetConnectionFlags(WMConnection
* cPtr
)
923 void WMSetConnectionFlags(WMConnection
* cPtr
, unsigned int flags
)
925 cPtr
->uflags
= flags
;
928 WMArray
*WMGetConnectionUnsentData(WMConnection
* cPtr
)
930 return cPtr
->outputQueue
;
933 void WMSetConnectionDefaultTimeout(unsigned int timeout
)
936 DefaultTimeout
= DEF_TIMEOUT
;
938 DefaultTimeout
= timeout
;
942 void WMSetConnectionOpenTimeout(unsigned int timeout
)
945 OpenTimeout
= DefaultTimeout
;
947 OpenTimeout
= timeout
;
951 void WMSetConnectionSendTimeout(WMConnection
* cPtr
, unsigned int timeout
)
954 cPtr
->sendTimeout
.timeout
= DefaultTimeout
;
956 cPtr
->sendTimeout
.timeout
= timeout
;