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
))
46 #if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD)
48 #endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */
50 cupsArrayRemove(Listeners
, lis
);
54 if (cupsArrayCount(Listeners
) == 0)
56 cupsArrayDelete(Listeners
);
63 * 'cupsdPauseListening()' - Clear input polling on all listening sockets...
67 cupsdPauseListening(void)
69 cupsd_listener_t
*lis
; /* Current listening socket */
72 if (cupsArrayCount(Listeners
) < 1)
75 if (cupsArrayCount(Clients
) == MaxClients
)
76 cupsdLogMessage(CUPSD_LOG_WARN
,
77 "Max clients reached, holding new connections...");
78 else if (errno
== ENFILE
|| errno
== EMFILE
)
79 cupsdLogMessage(CUPSD_LOG_WARN
,
80 "Too many open files, holding new connections for "
83 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdPauseListening: Clearing input bits...");
85 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
87 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
88 cupsdRemoveSelect(lis
->fd
);
90 ListeningPaused
= time(NULL
) + 30;
95 * 'cupsdResumeListening()' - Set input polling on all listening sockets...
99 cupsdResumeListening(void)
101 cupsd_listener_t
*lis
; /* Current listening socket */
104 if (cupsArrayCount(Listeners
) < 1)
107 cupsdLogMessage(CUPSD_LOG_INFO
, "Resuming new connection processing...");
108 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
109 "cupsdResumeListening: Setting input bits...");
111 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
113 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
114 cupsdAddSelect(lis
->fd
, (cupsd_selfunc_t
)cupsdAcceptClient
, NULL
, lis
);
121 * 'cupsdStartListening()' - Create all listening sockets...
125 cupsdStartListening(void)
127 int p
; /* Port number */
128 cupsd_listener_t
*lis
; /* Current listening socket */
129 char s
[256]; /* String addresss */
130 const char *have_domain
; /* Have a domain socket? */
131 static const char * const encryptions
[] =
132 { /* Encryption values */
140 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdStartListening: %d Listeners",
141 cupsArrayCount(Listeners
));
144 * Setup socket listeners...
147 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
), LocalPort
= 0,
150 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
152 httpAddrString(&(lis
->address
), s
, sizeof(s
));
153 p
= httpAddrPort(&(lis
->address
));
156 * If needed, create a socket for listening...
162 * Create a socket for listening...
165 lis
->fd
= httpAddrListen(&(lis
->address
), p
);
169 cupsdLogMessage(CUPSD_LOG_ERROR
,
170 "Unable to open listen socket for address %s:%d - %s.",
171 s
, p
, strerror(errno
));
175 * IPv6 is often disabled while DNS returns IPv6 addresses...
178 if (lis
->address
.addr
.sa_family
!= AF_INET6
&&
179 (FatalErrors
& CUPSD_FATAL_LISTEN
))
180 cupsdEndProcess(getpid(), 0);
182 if (FatalErrors
& CUPSD_FATAL_LISTEN
)
183 cupsdEndProcess(getpid(), 0);
184 #endif /* AF_INET6 */
191 cupsdLogMessage(CUPSD_LOG_INFO
, "Listening to %s:%d on fd %d...",
194 cupsdLogMessage(CUPSD_LOG_INFO
, "Listening to %s on fd %d...",
198 * Save the first port that is bound to the local loopback or
202 if ((!LocalPort
|| LocalEncryption
== HTTP_ENCRYPT_ALWAYS
) && p
> 0 &&
203 (httpAddrLocalhost(&(lis
->address
)) ||
204 httpAddrAny(&(lis
->address
))))
207 LocalEncryption
= lis
->encryption
;
211 if (lis
->address
.addr
.sa_family
== AF_LOCAL
&& !have_domain
)
212 have_domain
= lis
->address
.un
.sun_path
;
213 #endif /* AF_LOCAL */
217 * Make sure that we are listening on localhost!
220 if (!LocalPort
&& !have_domain
)
222 cupsdLogMessage(CUPSD_LOG_EMERG
,
223 "No Listen or Port lines were found to allow access via "
226 if (FatalErrors
& (CUPSD_FATAL_CONFIG
| CUPSD_FATAL_LISTEN
))
227 cupsdEndProcess(getpid(), 0);
231 * Set the CUPS_SERVER, IPP_PORT, and CUPS_ENCRYPTION variables based on
238 * Use domain sockets for the local connection...
241 cupsdSetEnv("CUPS_SERVER", have_domain
);
243 LocalEncryption
= HTTP_ENCRYPT_IF_REQUESTED
;
248 * Use the default local loopback address for the server...
251 cupsdSetEnv("CUPS_SERVER", "localhost");
254 cupsdSetEnv("CUPS_ENCRYPTION", encryptions
[LocalEncryption
]);
257 cupsdSetEnvf("IPP_PORT", "%d", LocalPort
);
260 * Resume listening for connections...
263 cupsdResumeListening();
268 * 'cupsdStopListening()' - Close all listening sockets...
272 cupsdStopListening(void)
274 cupsd_listener_t
*lis
; /* Current listening socket */
277 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
278 "cupsdStopListening: closing all listen sockets.");
280 cupsdPauseListening();
282 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
284 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
286 #if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD)
287 if (!lis
->on_demand
&& lis
->fd
!= -1)
289 httpAddrClose(&(lis
->address
), lis
->fd
);
296 httpAddrClose(&(lis
->address
), lis
->fd
);
299 #endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */