Skip to content

Commit

Permalink
DNS-SD device URI resolution: Cleaned API for upcoming libcups3 support
Browse files Browse the repository at this point in the history
For resolving DNS-SD-service-name-based device URIs for IPP printers
as CUPS uses them, libcups2 does not offer any useful API and we
therefore ended up implementing 2 workarounds.

One (cfResolveURI()) is using cupsBackendDeviceURI() but this function
is focused on use in CUPS backends, so we needed to use special tricks
to use it in a general library function, once redirecting stderr, to
eliminate log messages sent directly to stderr, and second,
temporarily unsetting the DEVICE_URI and PPD environment variables, ro
assure that the URI supplied to our function gets resolved and that
the resulting hostname/resource-based URI is always for the printing
and not for the fax part of the destination device.

The other (cfResolveURI2()) is calling `ippfind` as external
executable to poll the printer's DNS-SD record which contains all
components for the desired hostname/resource-based URI.

libcups3 now has added the new function httpResolveURI() to its API, a
function which formerly was library-internal, and does exactly what we
want, and without getting influenced by environment variables, not
polluting stderr, and with easy selection whether a print or fax URI
should be returned.

So with this commit we have adapted our API (and also slightly the
code) in praparation for the transition to libcups3 where we do all
DNS-SD device URI resolution with httpResolveURI(), no external
executable call or "abuse΅ of functions designed for other purposes.

We have

- Renamed cfippfindBasedURIConverter() to cfResolveURI2() to not have
  a mis-leading name and have two functions, cfResolveURI() for print
  URIs only and cfResolveURI2() to choose between print and fax URI.

- In the declaration of cfGetPrinterAttributes5() renamed the last
  parameter to is_fax, set to 1, we poll the fax part of the device,
  otherwise the print part.

- Let cfResolveURI2() only resolve the fax URI if is_fax is 1, and the
  print URI on any other value (0 and especially also the formerly
  used -1).

- Let cfResolveURI() also temporarily uset the PPD environment
  variable, so that cupsBackendDeviceURI() always returns the print
  URI.

This way the behavior of libcupsfilters will be the same for both
libcups2 and libcups3.
  • Loading branch information
tillkamppeter committed Apr 6, 2023
1 parent 6007f6f commit 54e1adc
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 35 deletions.
67 changes: 35 additions & 32 deletions cupsfilters/ipp.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,6 @@
#include <cupsfilters/ipp.h>


enum resolve_uri_converter_type // **** Resolving DNS-SD based URI ****
{
CUPS_BACKEND_URI_CONVERTER = -1,
IPPFIND_BASED_CONVERTER_FOR_PRINT_URI = 0,
IPPFIND_BASED_CONVERTER_FOR_FAX_URI = 1
};

char cf_get_printer_attributes_log[CF_GET_PRINTER_ATTRIBUTES_LOGSIZE];

static int
Expand Down Expand Up @@ -72,7 +65,7 @@ cfResolveURI(const char *raw_uri)
char *pseudo_argv[2];
const char *uri;
int fd1, fd2;
char *save_device_uri_var;
char *save_device_uri_var, *save_ppd_var;

// Eliminate any output to stderr, to get rid of the CUPS-backend-specific
// output of the cupsBackendDeviceURI() function
Expand All @@ -90,6 +83,17 @@ cfResolveURI(const char *raw_uri)
unsetenv("DEVICE_URI");
}

// Same for PPD, to make the cupsBackendDeviceURI() call in this
// function not do uncontrolled switches between print and fax URI
// dependent on the PPD file the variable is pointing to. This makes
// this function always return the print URI, to make the libcups2
// and libcups3 builds of libcupsfilters behave the same.
if ((save_ppd_var = getenv("PPD")) != NULL)
{
save_ppd_var = strdup(save_ppd_var);
unsetenv("PPD");
}

// Use the URI resolver of libcups to support DNS-SD-service-name-based
// URIs. The function returns the corresponding host-name-based URI
pseudo_argv[0] = (char *)raw_uri;
Expand All @@ -103,6 +107,13 @@ cfResolveURI(const char *raw_uri)
free(save_device_uri_var);
}

// Restore PPD environment variable if we had unset it
if (save_ppd_var)
{
setenv("PPD", save_ppd_var, 1);
free(save_ppd_var);
}

// Re-activate stderr output
dup2(fd1, 2);
close(fd1);
Expand Down Expand Up @@ -168,11 +179,11 @@ cfGetPrinterAttributes3(http_t *http_printer,
{
return (cfGetPrinterAttributes5(http_printer, raw_uri, pattrs, pattrs_size,
req_attrs, req_attrs_size, debug,
driverless_info, CUPS_BACKEND_URI_CONVERTER));
driverless_info, 0));
}

// Get attributes of a printer specified only by URI and given info about
// fax-support
// Get attributes of a printer or fax specified only by URI and given
// info about fax-support
ipp_t *cfGetPrinterAttributes4(const char* raw_uri,
const char* const pattrs[],
int pattrs_size,
Expand All @@ -181,19 +192,14 @@ ipp_t *cfGetPrinterAttributes4(const char* raw_uri,
int debug,
int is_fax)
{
if (is_fax)
return (cfGetPrinterAttributes5(NULL, raw_uri, pattrs, pattrs_size,
req_attrs, req_attrs_size, debug, NULL,
IPPFIND_BASED_CONVERTER_FOR_FAX_URI));
else
return (cfGetPrinterAttributes5(NULL, raw_uri, pattrs, pattrs_size,
req_attrs, req_attrs_size, debug, NULL,
IPPFIND_BASED_CONVERTER_FOR_PRINT_URI));
return (cfGetPrinterAttributes5(NULL, raw_uri, pattrs, pattrs_size,
req_attrs, req_attrs_size, debug, NULL,
is_fax));
}

// Get attributes of a printer specified by URI and under a given HTTP
// connection, for example via a domain socket, and give info about used
// fallbacks
// Get attributes of a printer or fax specified by URI and under a
// given HTTP connection, for example via a domain socket, and give
// info about used fallbacks
ipp_t *
cfGetPrinterAttributes5(http_t *http_printer,
const char* raw_uri,
Expand All @@ -203,7 +209,7 @@ cfGetPrinterAttributes5(http_t *http_printer,
int req_attrs_size,
int debug,
int* driverless_info,
int resolve_uri_type )
int is_fax)
{
char *uri;
int have_http, uri_status, host_port, i = 0, total_attrs = 0, fallback,
Expand Down Expand Up @@ -266,10 +272,7 @@ cfGetPrinterAttributes5(http_t *http_printer,
cf_get_printer_attributes_log[0] = '\0';

// Convert DNS-SD-service-name-based URIs to host-name-based URIs
if (resolve_uri_type == CUPS_BACKEND_URI_CONVERTER)
uri = cfResolveURI(raw_uri);
else
uri = cfippfindBasedURIConverter(raw_uri, resolve_uri_type);
uri = cfResolveURI2(raw_uri, is_fax);

if (uri == NULL)
{
Expand Down Expand Up @@ -491,7 +494,7 @@ cfGetPrinterAttributes5(http_t *http_printer,
}

char*
cfippfindBasedURIConverter (const char *uri, int is_fax)
cfResolveURI2 (const char *uri, int is_fax)
{
int ippfind_pid = 0, // Process ID of ippfind for IPP
post_proc_pipe[2], // Pipe to post-processing for IPP
Expand Down Expand Up @@ -550,7 +553,7 @@ cfippfindBasedURIConverter (const char *uri, int is_fax)
ippfind_argv[i++] = reg_type; // list IPP(S) entries
ippfind_argv[i++] = "-T"; // DNS-SD poll timeout
ippfind_argv[i++] = "0"; // Minimum time required
if (is_fax)
if (is_fax == 1)
{
ippfind_argv[i++] = "--txt";
ippfind_argv[i++] = "rfo";
Expand All @@ -560,7 +563,7 @@ cfippfindBasedURIConverter (const char *uri, int is_fax)
ippfind_argv[i++] = "-x";
ippfind_argv[i++] = "echo"; // Output the needed data fields
ippfind_argv[i++] = "-en"; // separated by tab characters
if(is_fax)
if(is_fax == 1)
ippfind_argv[i++] = "\n{service_hostname}\t{txt_rfo}\t{service_port}\t";
else
ippfind_argv[i++] = "\n{service_hostname}\t{txt_rp}\t{service_port}\t";
Expand Down Expand Up @@ -663,7 +666,7 @@ cfippfindBasedURIConverter (const char *uri, int is_fax)
(is_local ? "localhost" : service_hostname), port, "/%s",
resource_field);

if (is_fax)
if (is_fax == 1)
output_of_fax_uri = 1; // fax-uri requested from fax-capable device

read_error:
Expand Down Expand Up @@ -716,7 +719,7 @@ cfippfindBasedURIConverter (const char *uri, int is_fax)
}
}
}
if (is_fax && !output_of_fax_uri)
if (is_fax == 1 && !output_of_fax_uri)
goto error;

return (resolved_uri);
Expand Down
6 changes: 3 additions & 3 deletions cupsfilters/ipp.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ typedef enum cf_gen_sizes_mode_e
//

char *cfResolveURI(const char *raw_uri);
char *cfippfindBasedURIConverter(const char *uri ,int is_fax);
char *cfResolveURI2(const char *raw_uri, int is_fax);
int cfCheckDriverlessSupport(const char* uri);
ipp_t *cfGetPrinterAttributes(const char* raw_uri,
const char* const pattrs[],
Expand Down Expand Up @@ -113,7 +113,7 @@ ipp_t *cfGetPrinterAttributes4(const char* raw_uri,
const char* const req_attrs[],
int req_attrs_size,
int debug,
int isFax);
int is_fax);
ipp_t *cfGetPrinterAttributes5(http_t *http_printer,
const char* raw_uri,
const char* const pattrs[],
Expand All @@ -122,7 +122,7 @@ ipp_t *cfGetPrinterAttributes5(http_t *http_printer,
int req_attrs_size,
int debug,
int* driverless_support,
int resolve_uri_type);
int is_fax);

const char *cfIPPAttrEnumValForPrinter(ipp_t *printer_attrs,
ipp_t *job_attrs,
Expand Down

0 comments on commit 54e1adc

Please sign in to comment.