4 * Common network APIs for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2008 by Apple Inc.
7 * Copyright 2006-2007 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 * "LICENSE" which should have been included with this file. If this
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * backendCheckSideChannel() - Check the side-channel for pending requests.
20 * backendNetworkSideCB() - Handle common network side-channel commands.
21 * backendResolveURI() - Get the device URI, resolving as needed.
22 * resolve_callback() - Build a device URI for the given service name.
26 * Include necessary headers.
29 #include "backend-private.h"
32 # include <sys/time.h>
34 # include <sys/select.h>
38 #endif /* HAVE_DNSSD */
46 static void resolve_callback(DNSServiceRef sdRef
, DNSServiceFlags flags
,
47 uint32_t interfaceIndex
,
48 DNSServiceErrorType errorCode
,
49 const char *fullName
, const char *hostTarget
,
50 uint16_t port
, uint16_t txtLen
,
51 const unsigned char *txtRecord
, void *context
);
52 #endif /* HAVE_DNSSD */
56 * 'backendCheckSideChannel()' - Check the side-channel for pending requests.
61 backendCheckSideChannel(
62 int snmp_fd
, /* I - SNMP socket */
63 http_addr_t
*addr
) /* I - Address of device */
65 fd_set input
; /* Select input set */
66 struct timeval timeout
; /* Select timeout */
70 FD_SET(CUPS_SC_FD
, &input
);
72 timeout
.tv_sec
= timeout
.tv_usec
= 0;
74 if (select(CUPS_SC_FD
+ 1, &input
, NULL
, NULL
, &timeout
) > 0)
75 backendNetworkSideCB(-1, -1, snmp_fd
, addr
, 0);
80 * 'backendNetworkSideCB()' - Handle common network side-channel commands.
85 int print_fd
, /* I - Print file or -1 */
86 int device_fd
, /* I - Device file or -1 */
87 int snmp_fd
, /* I - SNMP socket */
88 http_addr_t
*addr
, /* I - Address of device */
89 int use_bc
) /* I - Use back-channel data? */
91 cups_sc_command_t command
; /* Request command */
92 cups_sc_status_t status
; /* Request/response status */
93 char data
[2048]; /* Request/response data */
94 int datalen
; /* Request/response data size */
95 const char *device_id
; /* 1284DEVICEID env var */
98 datalen
= sizeof(data
);
100 if (cupsSideChannelRead(&command
, &status
, data
, &datalen
, 1.0))
102 _cupsLangPuts(stderr
, _("WARNING: Failed to read side-channel request!\n"));
108 case CUPS_SC_CMD_DRAIN_OUTPUT
:
110 * Our sockets disable the Nagle algorithm and data is sent immediately.
114 status
= CUPS_SC_STATUS_NOT_IMPLEMENTED
;
115 else if (backendDrainOutput(print_fd
, device_fd
))
116 status
= CUPS_SC_STATUS_IO_ERROR
;
118 status
= CUPS_SC_STATUS_OK
;
123 case CUPS_SC_CMD_GET_BIDI
:
128 case CUPS_SC_CMD_GET_DEVICE_ID
:
131 cups_snmp_t packet
; /* Packet from printer */
132 static const int ppmPrinterIEEE1284DeviceId
[] =
133 { CUPS_OID_ppmPrinterIEEE1284DeviceId
,1,-1 };
135 if (_cupsSNMPWrite(snmp_fd
, addr
, 1, _cupsSNMPDefaultCommunity(),
136 CUPS_ASN1_GET_REQUEST
, 1,
137 ppmPrinterIEEE1284DeviceId
))
139 if (_cupsSNMPRead(snmp_fd
, &packet
, 1.0) &&
140 packet
.object_type
== CUPS_ASN1_OCTET_STRING
)
142 strlcpy(data
, packet
.object_value
.string
, sizeof(data
));
143 datalen
= (int)strlen(data
);
149 if ((device_id
= getenv("1284DEVICEID")) != NULL
)
151 strlcpy(data
, device_id
, sizeof(data
));
152 datalen
= (int)strlen(data
);
157 status
= CUPS_SC_STATUS_NOT_IMPLEMENTED
;
162 cupsSideChannelWrite(command
, status
, data
, datalen
, 1.0);
167 * 'backendResolveURI()' - Get the device URI, resolving as needed.
170 const char * /* O - Device URI */
171 backendResolveURI(char **argv
) /* I - Command-line arguments */
173 const char *uri
; /* Device URI */
174 char scheme
[32], /* URI components... */
179 http_uri_status_t status
; /* URI decode status */
182 * Get the device URI...
185 uri
= cupsBackendDeviceURI(argv
);
187 if ((status
= httpSeparateURI(HTTP_URI_CODING_ALL
, uri
, scheme
,
188 sizeof(scheme
), userpass
, sizeof(userpass
),
189 hostname
, sizeof(hostname
), &port
,
190 resource
, sizeof(resource
))) < HTTP_URI_OK
)
192 fprintf(stderr
, "ERROR: Bad device URI \"%s\" (%d)!\n", uri
, status
);
193 exit (CUPS_BACKEND_STOP
);
197 * Resolve it as needed...
200 if (strstr(hostname
, "._tcp"))
203 DNSServiceRef ref
; /* DNS-SD service reference */
204 char *regtype
, /* Pointer to type in hostname */
205 *domain
; /* Pointer to domain in hostname */
206 static char resolved_uri
[HTTP_MAX_URI
];
207 /* Resolved device URI */
210 * Separate the hostname into service name, registration type, and domain...
213 regtype
= strchr(hostname
, '.');
216 domain
= regtype
+ strlen(regtype
) - 1;
217 if (domain
> regtype
&& *domain
== '.')
220 for (domain
= strchr(regtype
, '.');
222 domain
= strchr(domain
+ 1, '.'))
223 if (domain
[1] != '_')
230 "DEBUG: Resolving service \"%s\", regtype \"%s\", domain \"%s\"\n",
231 hostname
, regtype
, domain
? domain
: "(null)");
233 if (DNSServiceResolve(&ref
, 0, 0, hostname
, regtype
, domain
,
235 resolved_uri
) == kDNSServiceErr_NoError
)
237 if (DNSServiceProcessResult(ref
) != kDNSServiceErr_NoError
)
242 DNSServiceRefDeallocate(ref
);
245 #endif /* HAVE_DNSSD */
251 fprintf(stderr
, "ERROR: Unable to resolve DNS-SD service \"%s\"!\n", uri
);
252 exit(CUPS_BACKEND_STOP
);
262 * 'resolve_callback()' - Build a device URI for the given service name.
267 DNSServiceRef sdRef
, /* I - Service reference */
268 DNSServiceFlags flags
, /* I - Results flags */
269 uint32_t interfaceIndex
, /* I - Interface number */
270 DNSServiceErrorType errorCode
, /* I - Error, if any */
271 const char *fullName
, /* I - Full service name */
272 const char *hostTarget
, /* I - Hostname */
273 uint16_t port
, /* I - Port number */
274 uint16_t txtLen
, /* I - Length of TXT record */
275 const unsigned char *txtRecord
, /* I - TXT record data */
276 void *context
) /* I - Pointer to URI buffer */
278 const char *scheme
; /* URI scheme */
279 char rp
[257]; /* Remote printer */
280 const void *value
; /* Value from TXT record */
281 uint8_t valueLen
; /* Length of value */
285 "DEBUG2: resolve_callback(sdRef=%p, flags=%x, interfaceIndex=%u, "
286 "errorCode=%d, fullName=\"%s\", hostTarget=\"%s\", port=%u, "
287 "txtLen=%u, txtRecord=%p, context=%p)\n", sdRef
, flags
,
288 interfaceIndex
, errorCode
, fullName
, hostTarget
, port
, txtLen
,
292 * Figure out the scheme from the full name...
295 if (strstr(fullName
, "._ipp"))
297 else if (strstr(fullName
, "._printer."))
299 else if (strstr(fullName
, "._pdl-datastream."))
302 scheme
= "riousbprint";
305 * Extract the "remote printer" key from the TXT record...
308 if ((value
= TXTRecordGetValuePtr(txtLen
, txtRecord
, "rp",
312 * Convert to resource by concatenating with a leading "/"...
316 memcpy(rp
+ 1, value
, valueLen
);
317 rp
[valueLen
+ 1] = '\0';
323 * Assemble the final device URI...
326 httpAssembleURI(HTTP_URI_CODING_ALL
, (char *)context
, HTTP_MAX_URI
, scheme
,
327 NULL
, hostTarget
, ntohs(port
), rp
);
329 fprintf(stderr
, "DEBUG: Resolved URI is \"%s\"...\n", (char *)context
);
331 #endif /* HAVE_DNSSD */