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 wwarning() calls that are still there.
31 #include "../src/config.h"
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
47 #include <sys/signal.h>
53 /* Some older systems does not define this (linux libc5, maybe others too) */
65 # define INADDR_NONE -1
68 /* Stuff for setting the sockets into non-blocking mode. */
69 /*#ifdef __POSIX_SOURCE
70 # define NONBLOCK_OPT O_NONBLOCK
72 # define NONBLOCK_OPT FNDELAY
75 #define NONBLOCK_OPT O_NONBLOCK
77 #define NETBUF_SIZE 4096
79 #define DEF_TIMEOUT 600 /* 600 seconds == 10 minutes */
85 static Bool SigInitialized
= False
;
87 static unsigned int DefaultTimeout
= DEF_TIMEOUT
;
88 static unsigned int OpenTimeout
= DEF_TIMEOUT
;
92 typedef struct TimeoutData
{
98 typedef struct W_Connection
{
99 int sock
; /* the socket we speak through */
102 WMHandlerID
*read
; /* the input read handler */
103 WMHandlerID
*write
; /* the input write handler */
104 WMHandlerID
*exception
; /* the input exception handler */
107 ConnectionDelegate
*delegate
; /* client delegates */
108 void *clientData
; /* client data */
109 unsigned int uflags
; /* flags for the client */
111 WMArray
*outputQueue
;
114 TimeoutData sendTimeout
;
115 TimeoutData openTimeout
;
117 WMConnectionState state
;
118 WMConnectionTimeoutState timeoutState
;
133 clearOutputQueue(WMConnection
*cPtr
) /*FOLD00*/
136 WMEmptyArray(cPtr
->outputQueue
);
141 openTimeout(void *cdata
) /*FOLD00*/
143 WMConnection
*cPtr
= (WMConnection
*) cdata
;
145 cPtr
->openTimeout
.handler
= NULL
;
146 if (cPtr
->handler
.write
) {
147 WMDeleteInputHandler(cPtr
->handler
.write
);
148 cPtr
->handler
.write
= NULL
;
150 if (cPtr
->state
!= WCConnected
) {
151 cPtr
->state
= WCTimedOut
;
152 cPtr
->timeoutState
= WCTWhileOpening
;
153 if (cPtr
->delegate
&& cPtr
->delegate
->didTimeout
) {
154 (*cPtr
->delegate
->didTimeout
)(cPtr
->delegate
, cPtr
);
156 WMCloseConnection(cPtr
);
157 cPtr
->state
= WCTimedOut
; /* the above set state to WCClosed */
164 sendTimeout(void *cdata
) /*FOLD00*/
166 WMConnection
*cPtr
= (WMConnection
*) cdata
;
168 cPtr
->sendTimeout
.handler
= NULL
;
169 if (cPtr
->handler
.write
) {
170 WMDeleteInputHandler(cPtr
->handler
.write
);
171 cPtr
->handler
.write
= NULL
;
173 if (WMGetArrayItemCount(cPtr
->outputQueue
)>0) {
174 clearOutputQueue(cPtr
);
175 cPtr
->state
= WCTimedOut
;
176 cPtr
->timeoutState
= WCTWhileSending
;
177 if (cPtr
->delegate
&& cPtr
->delegate
->didTimeout
) {
178 (*cPtr
->delegate
->didTimeout
)(cPtr
->delegate
, cPtr
);
180 WMCloseConnection(cPtr
);
181 cPtr
->state
= WCTimedOut
; /* the above set state to WCClosed */
188 inputHandler(int fd
, int mask
, void *clientData
) /*FOLD00*/
190 WMConnection
*cPtr
= (WMConnection
*)clientData
;
192 if (cPtr
->state
==WCClosed
|| cPtr
->state
==WCDied
)
195 if ((mask
& WIWriteMask
)) {
196 if (cPtr
->state
== WCInProgress
) {
199 int len
= sizeof(result
);
202 if (getsockopt(cPtr
->sock
, SOL_SOCKET
, SO_ERROR
,
203 (void*)&result
, &len
) == 0 && result
!= 0) {
204 cPtr
->state
= WCFailed
;
205 WCErrorCode
= result
;
207 /* should call wsyserrorwithcode(result, ...) here? */
209 cPtr
->state
= WCConnected
;
213 if (cPtr
->handler
.write
) {
214 WMDeleteInputHandler(cPtr
->handler
.write
);
215 cPtr
->handler
.write
= NULL
;
218 if (cPtr
->openTimeout
.handler
) {
219 WMDeleteTimerHandler(cPtr
->openTimeout
.handler
);
220 cPtr
->openTimeout
.handler
= NULL
;
223 if (cPtr
->delegate
&& cPtr
->delegate
->didInitialize
)
224 (*cPtr
->delegate
->didInitialize
)(cPtr
->delegate
, cPtr
);
226 /* we use failed and not cPtr->state here, because cPtr may be
227 * destroyed by the delegate called above if the connection failed
231 } else if (cPtr
->state
== WCConnected
) {
232 WMFlushConnection(cPtr
);
239 /* if the connection died, may get destroyed in the delegate, so retain */
242 if ((mask
& WIReadMask
) && cPtr
->delegate
->didReceiveInput
)
243 (*cPtr
->delegate
->didReceiveInput
)(cPtr
->delegate
, cPtr
);
245 if ((mask
& WIExceptMask
) && cPtr
->delegate
->didCatchException
)
246 (*cPtr
->delegate
->didCatchException
)(cPtr
->delegate
, cPtr
);
253 setSocketNonBlocking(int sock
, Bool flag
) /*FOLD00*/
258 state
= fcntl(sock
, F_GETFL
, 0);
261 /* set WCErrorCode here? -Dan*/
265 isNonBlock
= (state
& NONBLOCK_OPT
) != 0;
270 state
|= NONBLOCK_OPT
;
274 state
&= ~NONBLOCK_OPT
;
277 if (fcntl(sock
, F_SETFL
, state
) < 0) {
278 /* set WCErrorCode here? -Dan*/
287 setConnectionAddress(WMConnection
*cPtr
, struct sockaddr_in
*socketaddr
) /*FOLD00*/
289 wassertr(cPtr
->address
==NULL
);
291 cPtr
->address
= wstrdup(inet_ntoa(socketaddr
->sin_addr
));
292 cPtr
->service
= wmalloc(16);
293 sprintf(cPtr
->service
, "%hu", ntohs(socketaddr
->sin_port
));
294 cPtr
->protocol
= wstrdup("tcp");
298 static struct sockaddr_in
*
299 getSocketAddress(char* name
, char* service
, char* protocol
) /*FOLD00*/
301 static struct sockaddr_in socketaddr
;
304 if (!protocol
|| protocol
[0]==0)
307 memset(&socketaddr
, 0, sizeof(struct sockaddr_in
));
308 socketaddr
.sin_family
= AF_INET
;
311 * If we were given a hostname, we use any address for that host.
312 * Otherwise we expect the given name to be an address unless it is
313 * NULL (any address).
315 if (name
&& name
[0]!=0) {
316 WMHost
*host
= WMGetHostWithName(name
);
319 return NULL
; /* name is not a hostname nor a number and dot adr */
321 name
= WMGetHostAddress(host
);
322 #ifndef HAVE_INET_ATON
323 if ((socketaddr
.sin_addr
.s_addr
= inet_addr(name
)) == INADDR_NONE
) {
325 if (inet_aton(name
, &socketaddr
.sin_addr
) == 0) {
332 socketaddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
335 if (!service
|| service
[0]==0) {
336 socketaddr
.sin_port
= 0;
337 } else if ((sp
= getservbyname(service
, protocol
))==0) {
341 portNumber
= strtoul(service
, &endptr
, 10);
343 if (service
[0]!=0 && *endptr
==0 && portNumber
<65536) {
344 socketaddr
.sin_port
= htons(portNumber
);
349 socketaddr
.sin_port
= sp
->s_port
;
356 handle_sigpipe(int signum
)
358 if (0) signum
=0; /* To avoid a gcc warning */
363 createConnectionWithSocket(int sock
, Bool closeOnRelease
) /*FOLD00*/
366 struct sigaction sig_action
;
368 cPtr
= wmalloc(sizeof(WMConnection
));
370 memset(cPtr
, 0, sizeof(WMConnection
));
372 fcntl(sock
, F_SETFD
, FD_CLOEXEC
); /* by default close on exec */
375 cPtr
->openTimeout
.timeout
= OpenTimeout
;
376 cPtr
->openTimeout
.handler
= NULL
;
377 cPtr
->sendTimeout
.timeout
= DefaultTimeout
;
378 cPtr
->sendTimeout
.handler
= NULL
;
379 cPtr
->closeOnRelease
= closeOnRelease
;
381 WMCreateArrayWithDestructor(16, (WMFreeDataProc
*)WMReleaseData
);
382 cPtr
->state
= WCNotConnected
;
383 cPtr
->timeoutState
= WCTNone
;
385 /* ignore dead pipe */
386 if (!SigInitialized
) {
387 sig_action
.sa_handler
= &handle_sigpipe
;
388 /* Because POSIX mandates that only signal with handlers are reset
389 accross an exec*(), we do not want to propagate ignoring SIGPIPEs
390 to children. Hence the dummy handler.
391 Philippe Troin <phil@fifi.org>
393 sig_action
.sa_flags
= SA_RESTART
;
394 sigaction(SIGPIPE
, &sig_action
, NULL
);
395 SigInitialized
= True
;
404 WMCreateConnectionWithSocket(int sock
, Bool closeOnRelease
) /*FOLD00*/
407 struct sockaddr_in clientname
;
411 cPtr
= createConnectionWithSocket(sock
, closeOnRelease
);
412 cPtr
->wasNonBlocking
= WMIsConnectionNonBlocking(cPtr
);
413 cPtr
->isNonBlocking
= cPtr
->wasNonBlocking
;
415 /* some way to find out if it is connected, and binded. can't find
416 if it listens though!!!
419 size
= sizeof(clientname
);
420 n
= getpeername(sock
, (struct sockaddr
*) &clientname
, &size
);
422 /* Since we have a peer, it means we are connected */
423 cPtr
->state
= WCConnected
;
425 size
= sizeof(clientname
);
426 n
= getsockname(sock
, (struct sockaddr
*) &clientname
, &size
);
428 /* We don't have a peer, but we are binded to an address.
429 * Assume we are listening on it (we don't know that for sure!)
431 cPtr
->state
= WCListening
;
433 cPtr
->state
= WCNotConnected
;
443 * host is the name on which we want to listen for incoming connections,
444 * and it must be a name of this host, or NULL if we want to listen
445 * on any incoming address.
446 * service is either a service name as present in /etc/services, or the port
447 * number we want to listen on. If NULL, a random port between
448 * 1024 and 65535 will be assigned to us.
449 * protocol is one of "tcp" or "udp". If NULL, "tcp" will be used by default.
450 * currently only "tcp" is supported.
453 WMCreateConnectionAsServerAtAddress(char *host
, char *service
, char *protocol
) /*FOLD00*/
456 struct sockaddr_in
*socketaddr
;
462 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
463 wwarning(_("Bad address-service-protocol combination"));
467 /* Create the actual socket */
468 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
475 * Set socket options. We try to make the port reusable and have it
476 * close as fast as possible without waiting in unnecessary wait states
480 setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, (void *)&on
, sizeof(on
));
482 if (bind(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
488 if (listen(sock
, 10) < 0) {
494 /* Find out what is the address/service/protocol we get */
495 /* In case some of address/service/protocol were NULL */
496 size
= sizeof(*socketaddr
);
497 if (getsockname(sock
, (struct sockaddr
*)socketaddr
, &size
) < 0) {
503 cPtr
= createConnectionWithSocket(sock
, True
);
504 cPtr
->state
= WCListening
;
505 WMSetConnectionNonBlocking(cPtr
, True
);
507 setConnectionAddress(cPtr
, socketaddr
);
514 WMCreateConnectionToAddress(char *host
, char *service
, char *protocol
) /*FOLD00*/
517 struct sockaddr_in
*socketaddr
;
522 wassertrv(service
!=NULL
&& service
[0]!=0, NULL
);
524 if (host
==NULL
|| host
[0]==0)
527 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
528 wwarning(_("Bad address-service-protocol combination"));
532 /* Create the actual socket */
533 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
538 /* make socket blocking while we connect. */
539 setSocketNonBlocking(sock
, False
);
540 if (connect(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
546 cPtr
= createConnectionWithSocket(sock
, True
);
547 cPtr
->state
= WCConnected
;
548 WMSetConnectionNonBlocking(cPtr
, True
);
549 setConnectionAddress(cPtr
, socketaddr
);
556 WMCreateConnectionToAddressAndNotify(char *host
, char *service
, char *protocol
) /*FOLD00*/
559 struct sockaddr_in
*socketaddr
;
565 wassertrv(service
!=NULL
&& service
[0]!=0, NULL
);
567 if (host
==NULL
|| host
[0]==0)
570 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
571 wwarning(_("Bad address-service-protocol combination"));
575 /* Create the actual socket */
576 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
581 isNonBlocking
= setSocketNonBlocking(sock
, True
);
582 if (connect(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
583 if (errno
!=EINPROGRESS
) {
590 cPtr
= createConnectionWithSocket(sock
, True
);
591 cPtr
->state
= WCInProgress
;
592 cPtr
->isNonBlocking
= isNonBlocking
;
594 cPtr
->handler
.write
= WMAddInputHandler(cPtr
->sock
, WIWriteMask
,
597 cPtr
->openTimeout
.handler
=
598 WMAddTimerHandler(cPtr
->openTimeout
.timeout
*1000, openTimeout
, cPtr
);
600 setConnectionAddress(cPtr
, socketaddr
);
607 removeAllHandlers(WMConnection
*cPtr
) /*FOLD00*/
609 if (cPtr
->handler
.read
)
610 WMDeleteInputHandler(cPtr
->handler
.read
);
611 if (cPtr
->handler
.write
)
612 WMDeleteInputHandler(cPtr
->handler
.write
);
613 if (cPtr
->handler
.exception
)
614 WMDeleteInputHandler(cPtr
->handler
.exception
);
615 if (cPtr
->openTimeout
.handler
)
616 WMDeleteTimerHandler(cPtr
->openTimeout
.handler
);
617 if (cPtr
->sendTimeout
.handler
)
618 WMDeleteTimerHandler(cPtr
->sendTimeout
.handler
);
620 cPtr
->handler
.read
= NULL
;
621 cPtr
->handler
.write
= NULL
;
622 cPtr
->handler
.exception
= NULL
;
623 cPtr
->openTimeout
.handler
= NULL
;
624 cPtr
->sendTimeout
.handler
= NULL
;
629 WMDestroyConnection(WMConnection
*cPtr
) /*FOLD00*/
631 if (cPtr
->closeOnRelease
&& cPtr
->sock
>=0) {
632 shutdown(cPtr
->sock
, SHUT_RDWR
);
636 removeAllHandlers(cPtr
);
637 WMFreeArray(cPtr
->outputQueue
); /* will also free the items with the destructor */
640 wfree(cPtr
->address
);
641 wfree(cPtr
->service
);
642 wfree(cPtr
->protocol
);
650 WMCloseConnection(WMConnection
*cPtr
) /*FOLD00*/
653 shutdown(cPtr
->sock
, SHUT_RDWR
);
658 removeAllHandlers(cPtr
);
659 clearOutputQueue(cPtr
);
661 cPtr
->state
= WCClosed
;
666 WMAcceptConnection(WMConnection
*listener
) /*FOLD00*/
668 struct sockaddr_in clientname
;
671 WMConnection
*newConnection
;
674 wassertrv(listener
&& listener
->state
==WCListening
, NULL
);
676 size
= sizeof(clientname
);
677 newSock
= accept(listener
->sock
, (struct sockaddr
*) &clientname
, &size
);
679 WCErrorCode
= ((errno
!=EAGAIN
&& errno
!=EWOULDBLOCK
) ? errno
: 0);
683 newConnection
= createConnectionWithSocket(newSock
, True
);
684 WMSetConnectionNonBlocking(newConnection
, True
);
685 newConnection
->state
= WCConnected
;
686 setConnectionAddress(newConnection
, &clientname
);
688 return newConnection
;
693 WMGetConnectionAddress(WMConnection
*cPtr
) /*FOLD00*/
695 return cPtr
->address
;
700 WMGetConnectionService(WMConnection
*cPtr
) /*FOLD00*/
702 return cPtr
->service
;
707 WMGetConnectionProtocol(WMConnection
*cPtr
) /*FOLD00*/
709 return cPtr
->protocol
;
714 WMGetConnectionSocket(WMConnection
*cPtr
) /*FOLD00*/
721 WMGetConnectionState(WMConnection
*cPtr
) /*FOLD00*/
727 WMConnectionTimeoutState
728 WMGetConnectionTimeoutState(WMConnection
*cPtr
) /*FOLD00*/
730 return cPtr
->timeoutState
;
735 WMEnqueueConnectionData(WMConnection
*cPtr
, WMData
*data
) /*FOLD00*/
737 wassertrv(cPtr
->state
!=WCNotConnected
&& cPtr
->state
!=WCListening
, False
);
738 wassertrv(cPtr
->state
!=WCInProgress
&& cPtr
->state
!=WCFailed
, False
);
740 if (cPtr
->state
!=WCConnected
)
743 WMAddToArray(cPtr
->outputQueue
, WMRetainData(data
));
749 WMSendConnectionData(WMConnection
*cPtr
, WMData
*data
) /*FOLD00*/
751 int bytes
, pos
, len
, totalTransfer
;
752 TimeoutData
*tPtr
= &cPtr
->sendTimeout
;
753 const unsigned char *dataBytes
;
755 wassertrv(cPtr
->state
!=WCNotConnected
&& cPtr
->state
!=WCListening
, -1);
756 wassertrv(cPtr
->state
!=WCInProgress
&& cPtr
->state
!=WCFailed
, -1);
758 if (cPtr
->state
!=WCConnected
)
761 /* If we have no data just flush the queue, else try to send data */
762 if (data
&& WMGetDataLength(data
)>0) {
763 WMAddToArray(cPtr
->outputQueue
, WMRetainData(data
));
764 /* If there already was something in queue, and also a write input
765 * handler is established, it means we were unable to send, so
766 * return and let the write handler notify us when we can send.
768 if (WMGetArrayItemCount(cPtr
->outputQueue
)>1 && cPtr
->handler
.write
)
774 while (WMGetArrayItemCount(cPtr
->outputQueue
) > 0) {
775 data
= WMGetFromArray(cPtr
->outputQueue
, 0);
776 dataBytes
= (const unsigned char *)WMDataBytes(data
);
777 len
= WMGetDataLength(data
);
778 pos
= cPtr
->bufPos
; /* where we're left last time */
781 bytes
= write(cPtr
->sock
, dataBytes
+pos
, len
- pos
);
787 /* save the position where we're left and add a timeout */
789 if (!tPtr
->handler
) {
790 tPtr
->handler
= WMAddTimerHandler(tPtr
->timeout
*1000,
793 if (!cPtr
->handler
.write
) {
794 cPtr
->handler
.write
=
795 WMAddInputHandler(cPtr
->sock
, WIWriteMask
,
798 return totalTransfer
;
801 cPtr
->state
= WCDied
;
802 removeAllHandlers(cPtr
);
803 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
804 (*cPtr
->delegate
->didDie
)(cPtr
->delegate
, cPtr
);
809 totalTransfer
+= bytes
;
811 WMDeleteFromArray(cPtr
->outputQueue
, 0);
814 WMDeleteTimerHandler(tPtr
->handler
);
815 tPtr
->handler
= NULL
;
817 if (cPtr
->handler
.write
) {
818 WMDeleteInputHandler(cPtr
->handler
.write
);
819 cPtr
->handler
.write
= NULL
;
823 return totalTransfer
;
828 * WMGetConnectionAvailableData(connection):
830 * will return a WMData structure containing the available data on the
831 * specified connection. If connection is non-blocking (default) and no data
832 * is available when this function is called, an empty WMData is returned.
834 * If an error occurs while reading or the other side closed connection,
835 * it will return NULL.
836 * Also trying to read from an already died or closed connection is
837 * considered to be an error condition, and will return NULL.
840 WMGetConnectionAvailableData(WMConnection
*cPtr
) /*FOLD00*/
842 char buffer
[NETBUF_SIZE
];
846 wassertrv(cPtr
->state
!=WCNotConnected
&& cPtr
->state
!=WCListening
, NULL
);
847 wassertrv(cPtr
->state
!=WCInProgress
&& cPtr
->state
!=WCFailed
, NULL
);
849 if (cPtr
->state
!=WCConnected
)
855 nbytes
= read(cPtr
->sock
, buffer
, NETBUF_SIZE
);
861 aData
= WMCreateDataWithCapacity(0);
865 cPtr
->state
= WCDied
;
866 removeAllHandlers(cPtr
);
867 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
868 (*cPtr
->delegate
->didDie
)(cPtr
->delegate
, cPtr
);
871 } else if (nbytes
==0) { /* the other side has closed connection */
872 cPtr
->state
= WCClosed
;
873 removeAllHandlers(cPtr
);
874 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
875 (*cPtr
->delegate
->didDie
)(cPtr
->delegate
, cPtr
);
877 aData
= WMCreateDataWithBytes(buffer
, nbytes
);
885 WMSetConnectionDelegate(WMConnection
*cPtr
, ConnectionDelegate
*delegate
) /*FOLD00*/
887 wassertr(cPtr
->sock
>= 0);
888 /* Don't try to set the delegate multiple times */
889 wassertr(cPtr
->delegate
== NULL
);
891 cPtr
->delegate
= delegate
;
892 if (delegate
&& delegate
->didReceiveInput
&& !cPtr
->handler
.read
)
893 cPtr
->handler
.read
= WMAddInputHandler(cPtr
->sock
, WIReadMask
,
895 if (delegate
&& delegate
->didCatchException
&& !cPtr
->handler
.exception
)
896 cPtr
->handler
.exception
= WMAddInputHandler(cPtr
->sock
, WIExceptMask
,
903 WMIsConnectionNonBlocking(WMConnection
*cPtr
) /*FOLD00*/
908 state
= fcntl(cPtr
->sock
, F_GETFL
, 0);
911 /* If we can't use fcntl on socket, this probably also means we could
912 * not use fcntl to set non-blocking mode, and since a socket defaults
913 * to blocking when created, return False as the best assumption */
917 return ((state
& NONBLOCK_OPT
)!=0);
919 return cPtr
->isNonBlocking
;
926 WMSetConnectionNonBlocking(WMConnection
*cPtr
, Bool flag
) /*FOLD00*/
928 wassertrv(cPtr
!=NULL
&& cPtr
->sock
>=0, False
);
930 if (cPtr
->isNonBlocking
== flag
)
933 if (setSocketNonBlocking(cPtr
->sock
, flag
)==True
) {
934 cPtr
->isNonBlocking
= flag
;
943 WMSetConnectionCloseOnExec(WMConnection
*cPtr
, Bool flag
)
945 wassertrv(cPtr
!=NULL
&& cPtr
->sock
>=0, False
);
947 if (fcntl(cPtr
->sock
, F_SETFD
, (flag
? FD_CLOEXEC
: 0)) < 0) {
956 WMGetConnectionClientData(WMConnection
*cPtr
) /*FOLD00*/
958 return cPtr
->clientData
;
963 WMSetConnectionClientData(WMConnection
*cPtr
, void *data
) /*FOLD00*/
965 cPtr
->clientData
= data
;
970 WMGetConnectionFlags(WMConnection
*cPtr
) /*FOLD00*/
977 WMSetConnectionFlags(WMConnection
*cPtr
, unsigned int flags
) /*FOLD00*/
979 cPtr
->uflags
= flags
;
984 WMGetConnectionUnsentData(WMConnection
*cPtr
)
986 return cPtr
->outputQueue
;
991 WMSetConnectionDefaultTimeout(unsigned int timeout
) /*FOLD00*/
994 DefaultTimeout
= DEF_TIMEOUT
;
996 DefaultTimeout
= timeout
;
1002 WMSetConnectionOpenTimeout(unsigned int timeout
) /*FOLD00*/
1005 OpenTimeout
= DefaultTimeout
;
1007 OpenTimeout
= timeout
;
1013 WMSetConnectionSendTimeout(WMConnection
*cPtr
, unsigned int timeout
) /*FOLD00*/
1016 cPtr
->sendTimeout
.timeout
= DefaultTimeout
;
1018 cPtr
->sendTimeout
.timeout
= timeout
;