[cups-devel] Using CUPS_HTTP_DEFAULT with cupsStartDestDocument/cupsWriteRequestData/cupsFinishDestDocument API (fwd)

Michael Sweet msweet at apple.com
Thu Jan 25 19:23:37 PST 2018


Sam,

There are still some spots that apparently don't support CUPS_HTTP_DEFAULT in 2.2.4 (I think the later 2.2.x releases fixed those), so the workaround (which is forwards and backwards compatible) is to open your own connection with:

    http_t *http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);

This is what the CUPS API functions do internally when passed CUPS_HTTP_DEFAULT.


> On Jan 24, 2018, at 7:59 PM, Sam Varshavchik <mrsam at courier-mta.com> wrote:
> 
> I'm following the sample code from https://www.cups.org/doc/cupspm.html#submitting-a-print-job with cups 2.2.4, and my results are that cupsFinishDestDocument() returns IPP_STATUS_ERROR_INTERNAL.
> 
> Digging into the code with gdb, the problem appears to be as follows. This is what happens at the very beginning of cupsFinishTestDocument() when it calls _cupsConnect(), because I'm passing CUPS_HTTP_DEFAULT, like the sample code does:
> 
> 998         if (strcmp(cg->http->hostname, cg->server) ||
> (gdb)
> 999             cg->ipp_port != httpAddrPort(cg->http->hostaddr) ||
> (gdb)
> 998         if (strcmp(cg->http->hostname, cg->server) ||
> (gdb)
> 1031            httpClose(cg->http);
> (gdb) p cg->http->hostaddr
> $1 = (http_addr_t *) 0x9c2dd8
> (gdb) p *cg->http->hostaddr
> $2 = {addr = {sa_family = 1, sa_data = "/var/run/cups/"}, ipv4 = {
>   sin_family = 1, sin_port = 30255, sin_addr = {s_addr = 1915712097},
>   sin_zero = "un/cups/"}, ipv6 = {sin6_family = 1, sin6_port = 30255,
>   sin6_flowinfo = 1915712097, sin6_addr = {__in6_u = {
>       __u6_addr8 = "un/cups/cups.soc", __u6_addr16 = {28277, 25391, 28789,
>         12147, 30051, 29552, 29486, 25455}, __u6_addr32 = {1664052853,
>         796094581, 1936749923, 1668248366}}}, sin6_scope_id = 107}, un = {
>   sun_family = 1,
>   sun_path = "/var/run/cups/cups.sock", '\000' <repeats 84 times>},
> pad = "\001\000/var/run/cups/cups.sock", '\000' <repeats 230 times>}
> (gdb) p htons(30255)
> $3 = 12150
> (gdb) p cg->ipp_port
> $4 = 631
> (gdb) where
> #0  _cupsConnect () at request.c:1031
> #1  0x00007ffff6cec0d6 in cupsFinishDestDocument (http=<optimized out>,
>   dest=0x965070, info=0x99c230) at dest-job.c:273
> 
> 
> _cupsConnect() appears to decide to close the current http connection and open a new one, because of the mismatch between the current connection's port, and the IPP port:
> 
> cg->ipp_port != httpAddrPort(cg->http->hostaddr) ||
> 
> cg->http->hostaddr appears to be the port of my current connection to the scheduler, which is in the middle of submitting the print job; and not port 631. So _cupsConnect() appears to be taking down my active connection, and creates a new one; and this ends up making cupsFinishDestDocument() very unhappy.
> 
> Rooting through the CUPS source, I see that cups/testdest.c also uses the cupsStartDestDocument(), cupsWriteRequestData(), and cupsFinishDestDocument() API; except that testdest.c does not use CUPS_HTTP_DEFAULT but, rather, appears to use additional API calls to establish a separate http connection for the purpose of submitting a print job.
> 
> Should I expect cupsStartDestDocument(), cupsWriteRequestData(), and cupsFinishDestDocument() to work with CUPS_HTTP_DEFAULT, like the sample code shows? Or is this a bug in cupsFinishDestDocument(). Looking at how cupsWriteRequestData() deals with CUPS_HTTP_DEFAULT: it does not call _cupsConnect(), but it calls _cupsGlobal() and manually fetches the global connection handle out of there. That seems to be what cupsFinishDestDocument() should be doing also.
> 
> _______________________________________________
> cups-devel mailing list
> cups-devel at cups.org
> https://lists.cups.org/mailman/listinfo/cups-devel

_________________________________________________________
Michael Sweet, Senior Printing System Engineer



More information about the cups-devel mailing list