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.
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.
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. */
70 # define NONBLOCK_OPT O_NONBLOCK
72 # define NONBLOCK_OPT FNDELAY
76 #define NONBLOCK_OPT O_NONBLOCK
78 #define NETBUF_SIZE 4096
80 #define DEF_TIMEOUT 600 /* 600 seconds == 10 minutes */
86 static Bool SigInitialized
= False
;
88 static unsigned int DefaultTimeout
= DEF_TIMEOUT
;
89 static unsigned int OpenTimeout
= DEF_TIMEOUT
;
93 typedef struct TimeoutData
{
99 typedef struct W_Connection
{
100 int sock
; /* the socket we speak through */
103 WMHandlerID
*read
; /* the input read handler */
104 WMHandlerID
*write
; /* the input write handler */
105 WMHandlerID
*exception
; /* the input exception handler */
108 ConnectionDelegate
*delegate
; /* client delegates */
109 void *clientData
; /* client data */
110 unsigned int uflags
; /* flags for the client */
112 WMArray
*outputQueue
;
115 TimeoutData sendTimeout
;
116 TimeoutData openTimeout
;
118 WMConnectionState state
;
119 WMConnectionTimeoutState timeoutState
;
126 Bool shutdownOnClose
;
135 clearOutputQueue(WMConnection
*cPtr
)
138 WMEmptyArray(cPtr
->outputQueue
);
143 openTimeout(void *cdata
)
145 WMConnection
*cPtr
= (WMConnection
*) cdata
;
147 cPtr
->openTimeout
.handler
= NULL
;
148 if (cPtr
->handler
.write
) {
149 WMDeleteInputHandler(cPtr
->handler
.write
);
150 cPtr
->handler
.write
= NULL
;
152 if (cPtr
->state
!= WCConnected
) {
153 cPtr
->state
= WCTimedOut
;
154 cPtr
->timeoutState
= WCTWhileOpening
;
155 if (cPtr
->delegate
&& cPtr
->delegate
->didTimeout
) {
156 (*cPtr
->delegate
->didTimeout
)(cPtr
->delegate
, cPtr
);
158 WMCloseConnection(cPtr
);
159 cPtr
->state
= WCTimedOut
; /* the above set state to WCClosed */
166 sendTimeout(void *cdata
)
168 WMConnection
*cPtr
= (WMConnection
*) cdata
;
170 cPtr
->sendTimeout
.handler
= NULL
;
171 if (cPtr
->handler
.write
) {
172 WMDeleteInputHandler(cPtr
->handler
.write
);
173 cPtr
->handler
.write
= NULL
;
175 if (WMGetArrayItemCount(cPtr
->outputQueue
)>0) {
176 clearOutputQueue(cPtr
);
177 cPtr
->state
= WCTimedOut
;
178 cPtr
->timeoutState
= WCTWhileSending
;
179 // should we close it no matter what (after calling the didTimeout
181 if (cPtr
->delegate
&& cPtr
->delegate
->didTimeout
) {
182 (*cPtr
->delegate
->didTimeout
)(cPtr
->delegate
, cPtr
);
184 WMCloseConnection(cPtr
);
185 cPtr
->state
= WCTimedOut
; /* the above set state to WCClosed */
192 inputHandler(int fd
, int mask
, void *clientData
)
194 WMConnection
*cPtr
= (WMConnection
*)clientData
;
196 if (cPtr
->state
==WCClosed
|| cPtr
->state
==WCDied
)
199 if ((mask
& WIWriteMask
)) {
202 if (cPtr
->state
== WCInProgress
) {
204 int len
= sizeof(result
);
207 if (getsockopt(cPtr
->sock
, SOL_SOCKET
, SO_ERROR
,
208 (void*)&result
, &len
) == 0 && result
!= 0) {
209 cPtr
->state
= WCFailed
;
210 WCErrorCode
= result
;
212 /* should call wsyserrorwithcode(result, ...) here? */
214 cPtr
->state
= WCConnected
;
218 if (cPtr
->handler
.write
) {
219 WMDeleteInputHandler(cPtr
->handler
.write
);
220 cPtr
->handler
.write
= NULL
;
223 if (cPtr
->openTimeout
.handler
) {
224 WMDeleteTimerHandler(cPtr
->openTimeout
.handler
);
225 cPtr
->openTimeout
.handler
= NULL
;
228 if (cPtr
->delegate
&& cPtr
->delegate
->didInitialize
)
229 (*cPtr
->delegate
->didInitialize
)(cPtr
->delegate
, cPtr
);
231 /* we use failed and not cPtr->state here, because cPtr may be
232 * destroyed by the delegate called above if the connection failed
236 } else if (cPtr
->state
== WCConnected
) {
237 result
= WMFlushConnection(cPtr
);
238 if (result
>0 && cPtr
->delegate
&& cPtr
->delegate
->canResumeSending
) {
239 (*cPtr
->delegate
->canResumeSending
)(cPtr
->delegate
, cPtr
);
247 /* if the connection died, may get destroyed in the delegate, so retain */
250 if ((mask
& WIReadMask
) && cPtr
->delegate
->didReceiveInput
)
251 (*cPtr
->delegate
->didReceiveInput
)(cPtr
->delegate
, cPtr
);
253 if ((mask
& WIExceptMask
) && cPtr
->delegate
->didCatchException
)
254 (*cPtr
->delegate
->didCatchException
)(cPtr
->delegate
, cPtr
);
261 setSocketNonBlocking(int sock
, Bool flag
)
266 state
= fcntl(sock
, F_GETFL
, 0);
269 /* set WCErrorCode here? -Dan*/
273 isNonBlock
= (state
& NONBLOCK_OPT
) != 0;
278 state
|= NONBLOCK_OPT
;
282 state
&= ~NONBLOCK_OPT
;
285 if (fcntl(sock
, F_SETFL
, state
) < 0) {
286 /* set WCErrorCode here? -Dan*/
295 setConnectionAddress(WMConnection
*cPtr
, struct sockaddr_in
*socketaddr
)
297 wassertr(cPtr
->address
==NULL
);
299 cPtr
->address
= wstrdup(inet_ntoa(socketaddr
->sin_addr
));
300 cPtr
->service
= wmalloc(16);
301 sprintf(cPtr
->service
, "%hu", ntohs(socketaddr
->sin_port
));
302 cPtr
->protocol
= wstrdup("tcp");
306 static struct sockaddr_in
*
307 getSocketAddress(char* name
, char* service
, char* protocol
)
309 static struct sockaddr_in socketaddr
;
312 if (!protocol
|| protocol
[0]==0)
315 memset(&socketaddr
, 0, sizeof(struct sockaddr_in
));
316 socketaddr
.sin_family
= AF_INET
;
319 * If we were given a hostname, we use any address for that host.
320 * Otherwise we expect the given name to be an address unless it is
321 * NULL (any address).
323 if (name
&& name
[0]!=0) {
324 WMHost
*host
= WMGetHostWithName(name
);
327 return NULL
; /* name is not a hostname nor a number and dot adr */
329 name
= WMGetHostAddress(host
);
330 #ifndef HAVE_INET_ATON
331 if ((socketaddr
.sin_addr
.s_addr
= inet_addr(name
)) == INADDR_NONE
) {
333 if (inet_aton(name
, &socketaddr
.sin_addr
) == 0) {
340 socketaddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
343 if (!service
|| service
[0]==0) {
344 socketaddr
.sin_port
= 0;
345 } else if ((sp
= getservbyname(service
, protocol
))==0) {
349 portNumber
= strtoul(service
, &endptr
, 10);
351 if (service
[0]!=0 && *endptr
==0 && portNumber
<65536) {
352 socketaddr
.sin_port
= htons(portNumber
);
357 socketaddr
.sin_port
= sp
->s_port
;
365 dummyHandler(int signum
)
371 createConnectionWithSocket(int sock
, Bool closeOnRelease
)
374 struct sigaction sig_action
;
376 cPtr
= wmalloc(sizeof(WMConnection
));
378 memset(cPtr
, 0, sizeof(WMConnection
));
380 fcntl(sock
, F_SETFD
, FD_CLOEXEC
); /* by default close on exec */
383 cPtr
->openTimeout
.timeout
= OpenTimeout
;
384 cPtr
->openTimeout
.handler
= NULL
;
385 cPtr
->sendTimeout
.timeout
= DefaultTimeout
;
386 cPtr
->sendTimeout
.handler
= NULL
;
387 cPtr
->closeOnRelease
= closeOnRelease
;
388 cPtr
->shutdownOnClose
= 1;
390 WMCreateArrayWithDestructor(16, (WMFreeDataProc
*)WMReleaseData
);
391 cPtr
->state
= WCNotConnected
;
392 cPtr
->timeoutState
= WCTNone
;
394 /* ignore dead pipe */
395 if (!SigInitialized
) {
396 /* Because POSIX mandates that only signal with handlers are reset
397 * accross an exec*(), we do not want to propagate ignoring SIGPIPEs
398 * to children. Hence the dummy handler. Philippe Troin <phil@fifi.org>
400 sig_action
.sa_handler
= &dummyHandler
;
401 sig_action
.sa_flags
= SA_RESTART
;
402 sigaction(SIGPIPE
, &sig_action
, NULL
);
403 SigInitialized
= True
;
412 WMCreateConnectionWithSocket(int sock
, Bool closeOnRelease
)
415 struct sockaddr_in clientname
;
419 cPtr
= createConnectionWithSocket(sock
, closeOnRelease
);
420 cPtr
->wasNonBlocking
= WMIsConnectionNonBlocking(cPtr
);
421 cPtr
->isNonBlocking
= cPtr
->wasNonBlocking
;
423 /* some way to find out if it is connected, and binded. can't find
424 if it listens though!!!
427 size
= sizeof(clientname
);
428 n
= getpeername(sock
, (struct sockaddr
*) &clientname
, &size
);
430 /* Since we have a peer, it means we are connected */
431 cPtr
->state
= WCConnected
;
433 size
= sizeof(clientname
);
434 n
= getsockname(sock
, (struct sockaddr
*) &clientname
, &size
);
436 /* We don't have a peer, but we are binded to an address.
437 * Assume we are listening on it (we don't know that for sure!)
439 cPtr
->state
= WCListening
;
441 cPtr
->state
= WCNotConnected
;
451 * host is the name on which we want to listen for incoming connections,
452 * and it must be a name of this host, or NULL if we want to listen
453 * on any incoming address.
454 * service is either a service name as present in /etc/services, or the port
455 * number we want to listen on. If NULL, a random port between
456 * 1024 and 65535 will be assigned to us.
457 * protocol is one of "tcp" or "udp". If NULL, "tcp" will be used by default.
458 * currently only "tcp" is supported.
461 WMCreateConnectionAsServerAtAddress(char *host
, char *service
, char *protocol
)
464 struct sockaddr_in
*socketaddr
;
470 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
471 wwarning(_("Bad address-service-protocol combination"));
475 /* Create the actual socket */
476 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
483 * Set socket options. We try to make the port reusable and have it
484 * close as fast as possible without waiting in unnecessary wait states
488 setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, (void *)&on
, sizeof(on
));
490 if (bind(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
496 if (listen(sock
, 10) < 0) {
502 /* Find out what is the address/service/protocol we get */
503 /* In case some of address/service/protocol were NULL */
504 size
= sizeof(*socketaddr
);
505 if (getsockname(sock
, (struct sockaddr
*)socketaddr
, &size
) < 0) {
511 cPtr
= createConnectionWithSocket(sock
, True
);
512 cPtr
->state
= WCListening
;
513 WMSetConnectionNonBlocking(cPtr
, True
);
515 setConnectionAddress(cPtr
, socketaddr
);
522 WMCreateConnectionToAddress(char *host
, char *service
, char *protocol
)
525 struct sockaddr_in
*socketaddr
;
530 wassertrv(service
!=NULL
&& service
[0]!=0, NULL
);
532 if (host
==NULL
|| host
[0]==0)
535 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
536 wwarning(_("Bad address-service-protocol combination"));
540 /* Create the actual socket */
541 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
546 /* make socket blocking while we connect. */
547 setSocketNonBlocking(sock
, False
);
548 if (connect(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
554 cPtr
= createConnectionWithSocket(sock
, True
);
555 cPtr
->state
= WCConnected
;
556 WMSetConnectionNonBlocking(cPtr
, True
);
557 setConnectionAddress(cPtr
, socketaddr
);
564 WMCreateConnectionToAddressAndNotify(char *host
, char *service
, char *protocol
)
567 struct sockaddr_in
*socketaddr
;
573 wassertrv(service
!=NULL
&& service
[0]!=0, NULL
);
575 if (host
==NULL
|| host
[0]==0)
578 if ((socketaddr
= getSocketAddress(host
, service
, protocol
)) == NULL
) {
579 wwarning(_("Bad address-service-protocol combination"));
583 /* Create the actual socket */
584 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
589 isNonBlocking
= setSocketNonBlocking(sock
, True
);
590 if (connect(sock
, (struct sockaddr
*)socketaddr
, sizeof(*socketaddr
)) < 0) {
591 if (errno
!=EINPROGRESS
) {
598 cPtr
= createConnectionWithSocket(sock
, True
);
599 cPtr
->state
= WCInProgress
;
600 cPtr
->isNonBlocking
= isNonBlocking
;
602 cPtr
->handler
.write
= WMAddInputHandler(cPtr
->sock
, WIWriteMask
,
605 cPtr
->openTimeout
.handler
=
606 WMAddTimerHandler(cPtr
->openTimeout
.timeout
*1000, openTimeout
, cPtr
);
608 setConnectionAddress(cPtr
, socketaddr
);
615 removeAllHandlers(WMConnection
*cPtr
)
617 if (cPtr
->handler
.read
)
618 WMDeleteInputHandler(cPtr
->handler
.read
);
619 if (cPtr
->handler
.write
)
620 WMDeleteInputHandler(cPtr
->handler
.write
);
621 if (cPtr
->handler
.exception
)
622 WMDeleteInputHandler(cPtr
->handler
.exception
);
623 if (cPtr
->openTimeout
.handler
)
624 WMDeleteTimerHandler(cPtr
->openTimeout
.handler
);
625 if (cPtr
->sendTimeout
.handler
)
626 WMDeleteTimerHandler(cPtr
->sendTimeout
.handler
);
628 cPtr
->handler
.read
= NULL
;
629 cPtr
->handler
.write
= NULL
;
630 cPtr
->handler
.exception
= NULL
;
631 cPtr
->openTimeout
.handler
= NULL
;
632 cPtr
->sendTimeout
.handler
= NULL
;
637 WMDestroyConnection(WMConnection
*cPtr
)
639 if (cPtr
->closeOnRelease
&& cPtr
->sock
>=0) {
640 if (cPtr
->shutdownOnClose
) {
641 shutdown(cPtr
->sock
, SHUT_RDWR
);
646 removeAllHandlers(cPtr
);
647 WMFreeArray(cPtr
->outputQueue
); /* will also free the items with the destructor */
650 wfree(cPtr
->address
);
651 wfree(cPtr
->service
);
652 wfree(cPtr
->protocol
);
660 WMCloseConnection(WMConnection
*cPtr
)
663 if (cPtr
->shutdownOnClose
) {
664 shutdown(cPtr
->sock
, SHUT_RDWR
);
670 removeAllHandlers(cPtr
);
671 clearOutputQueue(cPtr
);
673 cPtr
->state
= WCClosed
;
678 WMAcceptConnection(WMConnection
*listener
)
680 struct sockaddr_in clientname
;
683 WMConnection
*newConnection
;
686 wassertrv(listener
&& listener
->state
==WCListening
, NULL
);
688 size
= sizeof(clientname
);
689 newSock
= accept(listener
->sock
, (struct sockaddr
*) &clientname
, &size
);
691 WCErrorCode
= ((errno
!=EAGAIN
&& errno
!=EWOULDBLOCK
) ? errno
: 0);
695 newConnection
= createConnectionWithSocket(newSock
, True
);
696 WMSetConnectionNonBlocking(newConnection
, True
);
697 newConnection
->state
= WCConnected
;
698 setConnectionAddress(newConnection
, &clientname
);
700 return newConnection
;
705 WMGetConnectionAddress(WMConnection
*cPtr
)
707 return cPtr
->address
;
712 WMGetConnectionService(WMConnection
*cPtr
)
714 return cPtr
->service
;
719 WMGetConnectionProtocol(WMConnection
*cPtr
)
721 return cPtr
->protocol
;
726 WMGetConnectionSocket(WMConnection
*cPtr
)
733 WMGetConnectionState(WMConnection
*cPtr
)
739 WMConnectionTimeoutState
740 WMGetConnectionTimeoutState(WMConnection
*cPtr
)
742 return cPtr
->timeoutState
;
747 WMEnqueueConnectionData(WMConnection
*cPtr
, WMData
*data
)
749 wassertrv(cPtr
->state
!=WCNotConnected
&& cPtr
->state
!=WCListening
, False
);
750 wassertrv(cPtr
->state
!=WCInProgress
&& cPtr
->state
!=WCFailed
, False
);
752 if (cPtr
->state
!=WCConnected
)
755 WMAddToArray(cPtr
->outputQueue
, WMRetainData(data
));
762 * -1 - not connected or connection died while sending
763 * 0 - couldn't send the data (or part of it). data is saved in a queue
764 * and will be sent when possible. after it is sent the canResumeSending
765 * callback will be called.
766 * 1 - data was succesfully sent
769 WMSendConnectionData(WMConnection
*cPtr
, WMData
*data
)
772 TimeoutData
*tPtr
= &cPtr
->sendTimeout
;
773 const unsigned char *dataBytes
;
775 wassertrv(cPtr
->state
!=WCNotConnected
&& cPtr
->state
!=WCListening
, -1);
776 wassertrv(cPtr
->state
!=WCInProgress
&& cPtr
->state
!=WCFailed
, -1);
778 if (cPtr
->state
!=WCConnected
)
781 /* If we have no data just flush the queue, else try to send data */
782 if (data
&& WMGetDataLength(data
)>0) {
783 WMAddToArray(cPtr
->outputQueue
, WMRetainData(data
));
784 /* If there already was something in queue, and also a write input
785 * handler is established, it means we were unable to send, so
786 * return and let the write handler notify us when we can send.
788 if (WMGetArrayItemCount(cPtr
->outputQueue
)>1 && cPtr
->handler
.write
)
792 while (WMGetArrayItemCount(cPtr
->outputQueue
) > 0) {
793 data
= WMGetFromArray(cPtr
->outputQueue
, 0);
794 dataBytes
= (const unsigned char *)WMDataBytes(data
);
795 len
= WMGetDataLength(data
);
796 pos
= cPtr
->bufPos
; /* where we're left last time */
799 bytes
= write(cPtr
->sock
, dataBytes
+pos
, len
- pos
);
805 /* save the position where we're left and add a timeout */
807 if (!tPtr
->handler
) {
808 tPtr
->handler
= WMAddTimerHandler(tPtr
->timeout
*1000,
811 if (!cPtr
->handler
.write
) {
812 cPtr
->handler
.write
=
813 WMAddInputHandler(cPtr
->sock
, WIWriteMask
,
819 cPtr
->state
= WCDied
;
820 removeAllHandlers(cPtr
);
821 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
822 (*cPtr
->delegate
->didDie
)(cPtr
->delegate
, cPtr
);
828 WMDeleteFromArray(cPtr
->outputQueue
, 0);
831 WMDeleteTimerHandler(tPtr
->handler
);
832 tPtr
->handler
= NULL
;
834 /*if (cPtr->handler.write) {
835 WMDeleteInputHandler(cPtr->handler.write);
836 cPtr->handler.write = NULL;
840 if (cPtr
->handler
.write
) {
841 WMDeleteInputHandler(cPtr
->handler
.write
);
842 cPtr
->handler
.write
= NULL
;
850 * WMGetConnectionAvailableData(connection):
852 * will return a WMData structure containing the available data on the
853 * specified connection. If connection is non-blocking (default) and no data
854 * is available when this function is called, an empty WMData is returned.
856 * If an error occurs while reading or the other side closed connection,
857 * it will return NULL.
858 * Also trying to read from an already died or closed connection is
859 * considered to be an error condition, and will return NULL.
862 WMGetConnectionAvailableData(WMConnection
*cPtr
)
864 char buffer
[NETBUF_SIZE
];
868 wassertrv(cPtr
->state
!=WCNotConnected
&& cPtr
->state
!=WCListening
, NULL
);
869 wassertrv(cPtr
->state
!=WCInProgress
&& cPtr
->state
!=WCFailed
, NULL
);
871 if (cPtr
->state
!=WCConnected
)
877 nbytes
= read(cPtr
->sock
, buffer
, NETBUF_SIZE
);
883 aData
= WMCreateDataWithCapacity(0);
887 cPtr
->state
= WCDied
;
888 removeAllHandlers(cPtr
);
889 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
890 (*cPtr
->delegate
->didDie
)(cPtr
->delegate
, cPtr
);
893 } else if (nbytes
==0) { /* the other side has closed connection */
894 cPtr
->state
= WCClosed
;
895 removeAllHandlers(cPtr
);
896 if (cPtr
->delegate
&& cPtr
->delegate
->didDie
)
897 (*cPtr
->delegate
->didDie
)(cPtr
->delegate
, cPtr
);
899 aData
= WMCreateDataWithBytes(buffer
, nbytes
);
907 WMSetConnectionDelegate(WMConnection
*cPtr
, ConnectionDelegate
*delegate
)
909 wassertr(cPtr
->sock
>= 0);
910 /* Don't try to set the delegate multiple times */
911 wassertr(cPtr
->delegate
== NULL
);
913 cPtr
->delegate
= delegate
;
914 if (delegate
&& delegate
->didReceiveInput
&& !cPtr
->handler
.read
)
915 cPtr
->handler
.read
= WMAddInputHandler(cPtr
->sock
, WIReadMask
,
917 if (delegate
&& delegate
->didCatchException
&& !cPtr
->handler
.exception
)
918 cPtr
->handler
.exception
= WMAddInputHandler(cPtr
->sock
, WIExceptMask
,
925 WMIsConnectionNonBlocking(WMConnection
*cPtr
)
930 state
= fcntl(cPtr
->sock
, F_GETFL
, 0);
933 /* If we can't use fcntl on socket, this probably also means we could
934 * not use fcntl to set non-blocking mode, and since a socket defaults
935 * to blocking when created, return False as the best assumption */
939 return ((state
& NONBLOCK_OPT
)!=0);
941 return cPtr
->isNonBlocking
;
948 WMSetConnectionNonBlocking(WMConnection
*cPtr
, Bool flag
)
950 wassertrv(cPtr
!=NULL
&& cPtr
->sock
>=0, False
);
952 flag
= ((flag
==0) ? 0 : 1);
954 if (cPtr
->isNonBlocking
== flag
)
957 if (setSocketNonBlocking(cPtr
->sock
, flag
)==True
) {
958 cPtr
->isNonBlocking
= flag
;
967 WMSetConnectionCloseOnExec(WMConnection
*cPtr
, Bool flag
)
969 wassertrv(cPtr
!=NULL
&& cPtr
->sock
>=0, False
);
971 if (fcntl(cPtr
->sock
, F_SETFD
, ((flag
==0) ? 0 : FD_CLOEXEC
)) < 0) {
980 WMSetConnectionShutdownOnClose(WMConnection
*cPtr
, Bool flag
)
982 cPtr
->shutdownOnClose
= ((flag
==0) ? 0 : 1);
987 WMGetConnectionClientData(WMConnection
*cPtr
)
989 return cPtr
->clientData
;
994 WMSetConnectionClientData(WMConnection
*cPtr
, void *data
)
996 cPtr
->clientData
= data
;
1001 WMGetConnectionFlags(WMConnection
*cPtr
)
1003 return cPtr
->uflags
;
1008 WMSetConnectionFlags(WMConnection
*cPtr
, unsigned int flags
)
1010 cPtr
->uflags
= flags
;
1015 WMGetConnectionUnsentData(WMConnection
*cPtr
)
1017 return cPtr
->outputQueue
;
1022 WMSetConnectionDefaultTimeout(unsigned int timeout
)
1025 DefaultTimeout
= DEF_TIMEOUT
;
1027 DefaultTimeout
= timeout
;
1033 WMSetConnectionOpenTimeout(unsigned int timeout
)
1036 OpenTimeout
= DefaultTimeout
;
1038 OpenTimeout
= timeout
;
1044 WMSetConnectionSendTimeout(WMConnection
*cPtr
, unsigned int timeout
)
1047 cPtr
->sendTimeout
.timeout
= DefaultTimeout
;
1049 cPtr
->sendTimeout
.timeout
= timeout
;