OpenPrinting / cups

OpenPrinting CUPS Sources
https://openprinting.github.io/cups
Apache License 2.0
1.05k stars 187 forks source link

The strange behavior of cupsConnectDest #958

Closed xiaowen581 closed 4 months ago

xiaowen581 commented 4 months ago

Describe the bug

  1. Although the target machine cannot be connected, cupsConnectDest still returns a non-nullptr http_t*.
  2. The flags passed to cb are incorrect.
  3. cupsLastError() was not reset in cupsConnectDest.

Based on the above observations, I cannot determine whether the connection was successfully established through the results of cupsConnectDest...

To Reproduce sample:

    int my_connect_dests(void* user_data, unsigned flags, cups_dest_t* dest)
    {
        cout << std::hex << "\t in my_connect_dests: flags: 0x" << flags << ". dest: " << dest << endl;
    }
    ...
    char resource[256];
    // unreachable printer
    cups_dest_t* pdest1 = cupsGetDestWithURI(NULL, "ipp://10.96.117.136/printers/RICOH/.printer");
    // connectable printer
    cups_dest_t* pdest2 = cupsGetDestWithURI(NULL, "ipp://10.96.116.85/ipp/print");
    http_t* h1 = nullptr;
    http_t* h2 = nullptr;
    h1 = cupsConnectDest(pdest1, CUPS_DEST_FLAGS_DEVICE, 30000, NULL, resource, HTTP_MAX_URI, my_connect_dests, NULL);
    cout << std::hex << h1 << " " << cupsLastError() << " " << cupsLastErrorString() << endl;
    cups_dinfo_t* info1 = cupsCopyDestInfo(h1, pdest1);
    if (info1 == nullptr)
        cout << "info1: nullptr" << endl;
    else
        cout << "info1: " << std::hex << info1 << endl;

    h2 = cupsConnectDest(pdest2, CUPS_DEST_FLAGS_DEVICE, 30000, NULL, resource, HTTP_MAX_URI, my_connect_dests, NULL);
    cout << std::hex << h2 << " " << cupsLastError() << " " << cupsLastErrorString() << endl;
    cups_dinfo_t* info2 = cupsCopyDestInfo(h2, pdest2);
    if (info2 == nullptr)
        cout << "info2: nullptr" << endl;
    else
        cout << "info2: " << std::hex << info2 << endl;

the output:

         in my_connect_dests: flags: 0x11. dest: 0x5585a8eea0f0
         in my_connect_dests: flags: 0x21. dest: 0x5585a8eea0f0
         in my_connect_dests: flags: 0x0. dest: 0x5585a8eea0f0
0x5585a8ef01a0 502 Host is down
info1: nullptr
         in my_connect_dests: flags: 0x11. dest: 0x5585a8eea390
         in my_connect_dests: flags: 0x21. dest: 0x5585a8eea390
         in my_connect_dests: flags: 0x9. dest: 0x5585a8eea390
0x5585a8ef5c80 502 Service Unavailable
info2: 0x5585a8f28420

In the above case, pdest1 is a unreachable printer, but still get a non-nullptr http_t*(0x5585a8ef01a0 ), and flags changs from 0x11 -> 0x21 -> 0x0(CUPS_DEST_FLAGS_NONE) . pdest2 is a connectable printer, but flags changs from 0x11 -> 0x21 -> 0x9(CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_ERROR), and cupsLastError() returns 502.

Expected behavior There should be a way to determine if the connection is successful based on the result of cupsConnectDest.

System Information:

xiaowen581 commented 4 months ago

cupsConnectDest ... http = httpConnect2(hostname, port, addrlist, AF_UNSPEC, encryption, 1, 0, NULL); ★the seventh parameter means returns without connect, so http is always non-nullptr. ... if (!httpReconnect2(http, msec, cancel) && cb) ★httpReconnect2 returns 0 on success, but 0 is treated as an error. (cb)(user_data, CUPS_DEST_FLAGS_UNCONNECTED | CUPS_DEST_FLAGS_ERROR, dest); else if (cb) (cb)(user_data, CUPS_DEST_FLAGS_NONE, dest); return (http);