Skip to content

Commit 8304d6b

Browse files
committed
Fix "unreliable" discovery with ippfind as used by driverless backend (Issue #1211)
- Export _cupsGetClock private API. - Use _cupsGetClock in ippfind. - Drop "avahi_have_data" and adopt CUPS 2.5/3.0 processing strategy.
1 parent bcd4296 commit 8304d6b

3 files changed

Lines changed: 94 additions & 137 deletions

File tree

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Changes in CUPS v2.4.12 (YYYY-MM-DD)
2626
- Fixed attributes returned by the Create-Xxx-Subscriptions requests
2727
(Issue #1204)
2828
- Fixed `ippDateToTime` when using a non GMT/UTC timezone (Issue #1208)
29+
- Fixed DNS-SD discovery with `ippfind` (Issue #1211)
2930

3031

3132
Changes in CUPS v2.4.11 (2024-09-30)

cups/libcups2.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ _cupsEncodeOption
1616
_cupsEncodingName
1717
_cupsFilePeekAhead
1818
_cupsGet1284Values
19+
_cupsGetClock
1920
_cupsGetDestResource
2021
_cupsGetDests
2122
_cupsGetPassword

tools/ippfind.c

Lines changed: 92 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,14 @@
33
* commands such as IPP and Bonjour conformance tests. This tool is
44
* inspired by the UNIX "find" command, thus its name.
55
*
6-
* Copyright © 2020-2024 by OpenPrinting.
6+
* Copyright © 2020-2025 by OpenPrinting.
77
* Copyright © 2020 by the IEEE-ISTO Printer Working Group
88
* Copyright © 2008-2018 by Apple Inc.
99
*
1010
* Licensed under Apache License v2.0. See the file "LICENSE" for more
1111
* information.
1212
*/
1313

14-
/*
15-
* Include necessary headers.
16-
*/
17-
1814
#define _CUPS_NO_DEPRECATED
1915
#include <cups/cups-private.h>
2016
#ifdef _WIN32
@@ -129,7 +125,6 @@ typedef struct ippfind_srv_s /* Service information */
129125
static DNSServiceRef dnssd_ref; /* Master service reference */
130126
#elif defined(HAVE_AVAHI)
131127
static AvahiClient *avahi_client = NULL;/* Client information */
132-
static int avahi_got_data = 0; /* Got data from poll? */
133128
static AvahiSimplePoll *avahi_poll = NULL;
134129
/* Poll information */
135130
#endif /* HAVE_MDNSRESPONDER */
@@ -139,6 +134,7 @@ static int address_family = AF_UNSPEC;
139134
static int bonjour_error = 0; /* Error browsing/resolving? */
140135
static double bonjour_timeout = 1.0; /* Timeout in seconds */
141136
static int ipp_version = 20; /* IPP version for LIST */
137+
static double last_update = 0.0; /* Last update time */
142138

143139

144140
/*
@@ -170,7 +166,6 @@ static int eval_expr(ippfind_srv_t *service,
170166
static int exec_program(ippfind_srv_t *service, int num_args,
171167
char **args);
172168
static ippfind_srv_t *get_service(cups_array_t *services, const char *serviceName, const char *regtype, const char *replyDomain) _CUPS_NONNULL(1,2,3,4);
173-
static double get_time(void);
174169
static int list_service(ippfind_srv_t *service);
175170
static ippfind_expr_t *new_expr(ippfind_op_t op, int invert,
176171
const char *value, const char *regex,
@@ -1308,14 +1303,12 @@ main(int argc, /* I - Number of command-line args */
13081303
*/
13091304

13101305
if (bonjour_timeout > 1.0)
1311-
endtime = get_time() + bonjour_timeout;
1306+
endtime = _cupsGetClock() + bonjour_timeout;
13121307
else
1313-
endtime = get_time() + 300.0;
1308+
endtime = _cupsGetClock() + 300.0;
13141309

1315-
while (get_time() < endtime)
1310+
while (_cupsGetClock() < endtime)
13161311
{
1317-
int process = 0; /* Process services? */
1318-
13191312
#ifdef HAVE_MDNSRESPONDER
13201313
int fd = DNSServiceRefSockFD(dnssd_ref);
13211314
/* File descriptor for DNS-SD */
@@ -1337,18 +1330,8 @@ main(int argc, /* I - Number of command-line args */
13371330

13381331
DNSServiceProcessResult(dnssd_ref);
13391332
}
1340-
else
1341-
{
1342-
/*
1343-
* Time to process services...
1344-
*/
1345-
1346-
process = 1;
1347-
}
13481333

13491334
#elif defined(HAVE_AVAHI)
1350-
avahi_got_data = 0;
1351-
13521335
if (avahi_simple_poll_iterate(avahi_poll, 500) > 0)
13531336
{
13541337
/*
@@ -1359,108 +1342,103 @@ main(int argc, /* I - Number of command-line args */
13591342
return (IPPFIND_EXIT_BONJOUR);
13601343
}
13611344

1362-
if (!avahi_got_data)
1363-
{
1364-
/*
1365-
* Time to process services...
1366-
*/
1367-
1368-
process = 1;
1369-
}
13701345
#endif /* HAVE_MDNSRESPONDER */
13711346

1372-
if (process)
1373-
{
1374-
/*
1375-
* Process any services that we have found...
1376-
*/
1347+
/*
1348+
* Process any services that we have found...
1349+
*/
13771350

1378-
int active = 0, /* Number of active resolves */
1379-
processed = 0; /* Number of processed services */
1351+
int active = 0, /* Number of active resolves */
1352+
processed = 0; /* Number of processed services */
13801353

1381-
for (service = (ippfind_srv_t *)cupsArrayFirst(services);
1382-
service;
1383-
service = (ippfind_srv_t *)cupsArrayNext(services))
1384-
{
1385-
if (service->is_processed)
1386-
processed ++;
1354+
for (service = (ippfind_srv_t *)cupsArrayFirst(services);
1355+
service;
1356+
service = (ippfind_srv_t *)cupsArrayNext(services))
1357+
{
1358+
if (service->is_processed)
1359+
processed ++;
13871360

1388-
if (!service->ref && !service->is_resolved)
1389-
{
1390-
/*
1391-
* Found a service, now resolve it (but limit to 50 active resolves...)
1392-
*/
1361+
if (!service->ref && !service->is_resolved)
1362+
{
1363+
/*
1364+
* Found a service, now resolve it (but limit to 50 active resolves...)
1365+
*/
13931366

1394-
if (active < 50)
1395-
{
1367+
if (active < 50)
1368+
{
13961369
#ifdef HAVE_MDNSRESPONDER
1397-
service->ref = dnssd_ref;
1398-
err = DNSServiceResolve(&(service->ref),
1399-
kDNSServiceFlagsShareConnection, 0,
1400-
service->name, service->regtype,
1401-
service->domain, resolve_callback,
1402-
service);
1370+
service->ref = dnssd_ref;
1371+
err = DNSServiceResolve(&(service->ref),
1372+
kDNSServiceFlagsShareConnection, 0,
1373+
service->name, service->regtype,
1374+
service->domain, resolve_callback,
1375+
service);
14031376

14041377
#elif defined(HAVE_AVAHI)
1405-
service->ref = avahi_service_resolver_new(avahi_client,
1406-
AVAHI_IF_UNSPEC,
1407-
AVAHI_PROTO_UNSPEC,
1408-
service->name,
1409-
service->regtype,
1410-
service->domain,
1411-
AVAHI_PROTO_UNSPEC, 0,
1412-
resolve_callback,
1413-
service);
1414-
if (service->ref)
1415-
err = 0;
1416-
else
1417-
err = avahi_client_errno(avahi_client);
1378+
service->ref = avahi_service_resolver_new(avahi_client,
1379+
AVAHI_IF_UNSPEC,
1380+
AVAHI_PROTO_UNSPEC,
1381+
service->name,
1382+
service->regtype,
1383+
service->domain,
1384+
AVAHI_PROTO_UNSPEC, 0,
1385+
resolve_callback,
1386+
service);
1387+
if (service->ref)
1388+
err = 0;
1389+
else
1390+
err = avahi_client_errno(avahi_client);
14181391
#endif /* HAVE_MDNSRESPONDER */
14191392

1420-
if (err)
1421-
{
1422-
_cupsLangPrintf(stderr,
1423-
_("ippfind: Unable to browse or resolve: %s"),
1424-
dnssd_error_string(err));
1425-
return (IPPFIND_EXIT_BONJOUR);
1426-
}
1393+
if (err)
1394+
{
1395+
_cupsLangPrintf(stderr,
1396+
_("ippfind: Unable to browse or resolve: %s"),
1397+
dnssd_error_string(err));
1398+
return (IPPFIND_EXIT_BONJOUR);
1399+
}
14271400

1428-
active ++;
1429-
}
1430-
}
1431-
else if (service->is_resolved && !service->is_processed)
1432-
{
1433-
/*
1434-
* Resolved, not process this service against the expressions...
1435-
*/
1401+
active ++;
1402+
}
1403+
}
1404+
else if (service->is_resolved && !service->is_processed)
1405+
{
1406+
/*
1407+
* Resolved, not process this service against the expressions...
1408+
*/
14361409

1437-
if (service->ref)
1438-
{
1410+
if (service->ref)
1411+
{
14391412
#ifdef HAVE_MDNSRESPONDER
1440-
DNSServiceRefDeallocate(service->ref);
1413+
DNSServiceRefDeallocate(service->ref);
14411414
#else
1442-
avahi_service_resolver_free(service->ref);
1415+
avahi_service_resolver_free(service->ref);
14431416
#endif /* HAVE_MDNSRESPONDER */
14441417

1445-
service->ref = NULL;
1446-
}
1418+
service->ref = NULL;
1419+
}
14471420

1448-
if (eval_expr(service, expressions))
1449-
status = IPPFIND_EXIT_TRUE;
1421+
if (eval_expr(service, expressions))
1422+
status = IPPFIND_EXIT_TRUE;
14501423

1451-
service->is_processed = 1;
1452-
}
1453-
else if (service->ref)
1454-
active ++;
1424+
service->is_processed = 1;
14551425
}
1426+
else if (service->ref)
1427+
active ++;
1428+
}
14561429

1457-
/*
1458-
* If we have processed all services we have discovered, then we are done.
1459-
*/
1430+
/*
1431+
* If we have processed all services we have discovered, then we are done.
1432+
*/
14601433

1461-
if (processed == cupsArrayCount(services) && bonjour_timeout <= 1.0)
1462-
break;
1463-
}
1434+
if (processed > 0 && (processed == cupsArrayCount(services) || (_cupsGetClock() - last_update) >= 2.5) && bonjour_timeout <= 1.0)
1435+
break;
1436+
1437+
/*
1438+
* Give the browsers/resolvers some time...
1439+
*/
1440+
1441+
usleep(250000);
14641442
}
14651443

14661444
if (bonjour_error)
@@ -1490,6 +1468,8 @@ browse_callback(
14901468
* Only process "add" data...
14911469
*/
14921470

1471+
last_update = _cupsGetClock();
1472+
14931473
(void)sdRef;
14941474
(void)interfaceIndex;
14951475

@@ -1522,6 +1502,8 @@ browse_local_callback(
15221502
ippfind_srv_t *service; /* Service */
15231503

15241504

1505+
last_update = _cupsGetClock();
1506+
15251507
/*
15261508
* Only process "add" data...
15271509
*/
@@ -1565,6 +1547,8 @@ browse_callback(
15651547
ippfind_srv_t *service; /* Service information */
15661548

15671549

1550+
last_update = _cupsGetClock();
1551+
15681552
(void)interface;
15691553
(void)protocol;
15701554
(void)context;
@@ -2190,31 +2174,6 @@ get_service(cups_array_t *services, /* I - Service array */
21902174
}
21912175

21922176

2193-
/*
2194-
* 'get_time()' - Get the current time-of-day in seconds.
2195-
*/
2196-
2197-
static double
2198-
get_time(void)
2199-
{
2200-
#ifdef _WIN32
2201-
struct _timeb curtime; /* Current Windows time */
2202-
2203-
_ftime(&curtime);
2204-
2205-
return (curtime.time + 0.001 * curtime.millitm);
2206-
2207-
#else
2208-
struct timeval curtime; /* Current UNIX time */
2209-
2210-
if (gettimeofday(&curtime, NULL))
2211-
return (0.0);
2212-
else
2213-
return (curtime.tv_sec + 0.000001 * curtime.tv_usec);
2214-
#endif /* _WIN32 */
2215-
}
2216-
2217-
22182177
/*
22192178
* 'list_service()' - List the contents of a service.
22202179
*/
@@ -2517,7 +2476,7 @@ new_expr(ippfind_op_t op, /* I - Operation */
25172476
*
25182477
* Note: This function is needed because avahi_simple_poll_iterate is broken
25192478
* and always uses a timeout of 0 (!) milliseconds.
2520-
* (Avahi Ticket #364)
2479+
* (Avahi Github issue #127)
25212480
*/
25222481

25232482
static int /* O - Number of file descriptors matching */
@@ -2527,18 +2486,10 @@ poll_callback(
25272486
int timeout, /* I - Timeout in milliseconds (unused) */
25282487
void *context) /* I - User data (unused) */
25292488
{
2530-
int val; /* Return value */
2531-
2532-
25332489
(void)timeout;
25342490
(void)context;
25352491

2536-
val = poll(pollfds, num_pollfds, 500);
2537-
2538-
if (val > 0)
2539-
avahi_got_data = 1;
2540-
2541-
return (val);
2492+
return (poll(pollfds, num_pollfds, 500));
25422493
}
25432494
#endif /* HAVE_AVAHI */
25442495

@@ -2569,6 +2520,8 @@ resolve_callback(
25692520
/* Service */
25702521

25712522

2523+
last_update = _cupsGetClock();
2524+
25722525
/*
25732526
* Only process "add" data...
25742527
*/
@@ -2650,6 +2603,8 @@ resolve_callback(
26502603
AvahiStringList *current; /* Current TXT key/value pair */
26512604

26522605

2606+
last_update = _cupsGetClock();
2607+
26532608
(void)address;
26542609

26552610
if (event != AVAHI_RESOLVER_FOUND)

0 commit comments

Comments
 (0)