2 * "$Id: listen.c 12080 2014-08-04 13:23:50Z msweet $"
4 * Server listening routines for the CUPS scheduler.
6 * Copyright 2007-2014 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * Include necessary headers...
24 * Make sure the IPV6_V6ONLY is defined on Linux - older versions of
25 * glibc don't define it even if the kernel supports it...
28 #if defined(__linux) && !defined(IPV6_V6ONLY)
29 # define IPV6_V6ONLY 26
30 #endif /* __linux && !IPV6_V6ONLY */
34 * 'cupsdDeleteAllListeners()' - Delete all listeners.
38 cupsdDeleteAllListeners(void)
40 cupsd_listener_t
*lis
; /* Current listening socket */
43 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
45 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
48 cupsArrayDelete(Listeners
);
54 * 'cupsdPauseListening()' - Clear input polling on all listening sockets...
58 cupsdPauseListening(void)
60 cupsd_listener_t
*lis
; /* Current listening socket */
63 if (cupsArrayCount(Listeners
) < 1)
66 if (cupsArrayCount(Clients
) == MaxClients
)
67 cupsdLogMessage(CUPSD_LOG_WARN
,
68 "Max clients reached, holding new connections...");
69 else if (errno
== ENFILE
|| errno
== EMFILE
)
70 cupsdLogMessage(CUPSD_LOG_WARN
,
71 "Too many open files, holding new connections for "
74 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdPauseListening: Clearing input bits...");
76 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
78 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
79 cupsdRemoveSelect(lis
->fd
);
81 ListeningPaused
= time(NULL
) + 30;
86 * 'cupsdResumeListening()' - Set input polling on all listening sockets...
90 cupsdResumeListening(void)
92 cupsd_listener_t
*lis
; /* Current listening socket */
95 if (cupsArrayCount(Listeners
) < 1)
98 cupsdLogMessage(CUPSD_LOG_INFO
, "Resuming new connection processing...");
99 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
100 "cupsdResumeListening: Setting input bits...");
102 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
104 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
105 cupsdAddSelect(lis
->fd
, (cupsd_selfunc_t
)cupsdAcceptClient
, NULL
, lis
);
112 * 'cupsdStartListening()' - Create all listening sockets...
116 cupsdStartListening(void)
118 int p
; /* Port number */
119 cupsd_listener_t
*lis
; /* Current listening socket */
120 char s
[256]; /* String addresss */
121 const char *have_domain
; /* Have a domain socket? */
122 static const char * const encryptions
[] =
123 { /* Encryption values */
131 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdStartListening: %d Listeners",
132 cupsArrayCount(Listeners
));
135 * Setup socket listeners...
138 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
), LocalPort
= 0,
141 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
143 httpAddrString(&(lis
->address
), s
, sizeof(s
));
144 p
= httpAddrPort(&(lis
->address
));
147 * If needed, create a socket for listening...
153 * Create a socket for listening...
156 lis
->fd
= httpAddrListen(&(lis
->address
), p
);
160 cupsdLogMessage(CUPSD_LOG_ERROR
,
161 "Unable to open listen socket for address %s:%d - %s.",
162 s
, p
, strerror(errno
));
166 * IPv6 is often disabled while DNS returns IPv6 addresses...
169 if (lis
->address
.addr
.sa_family
!= AF_INET6
&&
170 (FatalErrors
& CUPSD_FATAL_LISTEN
))
171 cupsdEndProcess(getpid(), 0);
173 if (FatalErrors
& CUPSD_FATAL_LISTEN
)
174 cupsdEndProcess(getpid(), 0);
175 #endif /* AF_INET6 */
182 cupsdLogMessage(CUPSD_LOG_INFO
, "Listening to %s:%d on fd %d...",
185 cupsdLogMessage(CUPSD_LOG_INFO
, "Listening to %s on fd %d...",
189 * Save the first port that is bound to the local loopback or
193 if ((!LocalPort
|| LocalEncryption
== HTTP_ENCRYPT_ALWAYS
) && p
> 0 &&
194 (httpAddrLocalhost(&(lis
->address
)) ||
195 httpAddrAny(&(lis
->address
))))
198 LocalEncryption
= lis
->encryption
;
202 if (lis
->address
.addr
.sa_family
== AF_LOCAL
&& !have_domain
)
203 have_domain
= lis
->address
.un
.sun_path
;
204 #endif /* AF_LOCAL */
208 * Make sure that we are listening on localhost!
211 if (!LocalPort
&& !have_domain
)
213 cupsdLogMessage(CUPSD_LOG_EMERG
,
214 "No Listen or Port lines were found to allow access via "
217 if (FatalErrors
& (CUPSD_FATAL_CONFIG
| CUPSD_FATAL_LISTEN
))
218 cupsdEndProcess(getpid(), 0);
222 * Set the CUPS_SERVER, IPP_PORT, and CUPS_ENCRYPTION variables based on
229 * Use domain sockets for the local connection...
232 cupsdSetEnv("CUPS_SERVER", have_domain
);
234 LocalEncryption
= HTTP_ENCRYPT_IF_REQUESTED
;
239 * Use the default local loopback address for the server...
242 cupsdSetEnv("CUPS_SERVER", "localhost");
245 cupsdSetEnv("CUPS_ENCRYPTION", encryptions
[LocalEncryption
]);
248 cupsdSetEnvf("IPP_PORT", "%d", LocalPort
);
251 * Resume listening for connections...
254 cupsdResumeListening();
259 * 'cupsdStopListening()' - Close all listening sockets...
263 cupsdStopListening(void)
265 cupsd_listener_t
*lis
; /* Current listening socket */
268 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
269 "cupsdStopListening: closing all listen sockets.");
271 cupsdPauseListening();
273 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
275 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
277 #if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD)
278 if (lis
->fd
!= -1 && !lis
->on_demand
)
279 httpAddrClose(&(lis
->address
), lis
->fd
);
283 httpAddrClose(&(lis
->address
), lis
->fd
);
284 #endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */
292 * End of "$Id: listen.c 12080 2014-08-04 13:23:50Z msweet $".