Revert manifest to default one
[external/cups.git] / backend / network.c
1 /*
2  * "$Id: network.c 9578 2011-03-04 18:44:47Z mike $"
3  *
4  *   Common backend network APIs for CUPS.
5  *
6  *   Copyright 2007-2011 by Apple Inc.
7  *   Copyright 2006-2007 by Easy Software Products, all rights reserved.
8  *
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/".
14  *
15  *   This file is subject to the Apple OS-Developed Software exception.
16  *
17  * Contents:
18  *
19  *   backendCheckSideChannel() - Check the side-channel for pending requests.
20  *   backendNetworkSideCB()    - Handle common network side-channel commands.
21  */
22
23 /*
24  * Include necessary headers.
25  */
26
27 #include "backend-private.h"
28 #include <limits.h>
29 #ifdef __hpux
30 #  include <sys/time.h>
31 #else
32 #  include <sys/select.h>
33 #endif /* __hpux */
34
35
36 /*
37  * 'backendCheckSideChannel()' - Check the side-channel for pending requests.
38  */
39
40
41 void
42 backendCheckSideChannel(
43     int         snmp_fd,                /* I - SNMP socket */
44     http_addr_t *addr)                  /* I - Address of device */
45 {
46   fd_set        input;                  /* Select input set */
47   struct timeval timeout;               /* Select timeout */
48
49
50   FD_ZERO(&input);
51   FD_SET(CUPS_SC_FD, &input);
52
53   timeout.tv_sec = timeout.tv_usec = 0;
54
55   if (select(CUPS_SC_FD + 1, &input, NULL, NULL, &timeout) > 0)
56     backendNetworkSideCB(-1, -1, snmp_fd, addr, 0);
57 }
58
59
60 /*
61  * 'backendNetworkSideCB()' - Handle common network side-channel commands.
62  */
63
64 int                                     /* O - -1 on error, 0 on success */
65 backendNetworkSideCB(
66     int         print_fd,               /* I - Print file or -1 */
67     int         device_fd,              /* I - Device file or -1 */
68     int         snmp_fd,                /* I - SNMP socket */
69     http_addr_t *addr,                  /* I - Address of device */
70     int         use_bc)                 /* I - Use back-channel data? */
71 {
72   cups_sc_command_t     command;        /* Request command */
73   cups_sc_status_t      status;         /* Request/response status */
74   char                  data[2048];     /* Request/response data */
75   int                   datalen;        /* Request/response data size */
76   const char            *device_id;     /* 1284DEVICEID env var */
77
78
79   datalen = sizeof(data);
80
81   if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0))
82     return (-1);
83
84   switch (command)
85   {
86     case CUPS_SC_CMD_DRAIN_OUTPUT :
87        /*
88         * Our sockets disable the Nagle algorithm and data is sent immediately.
89         */
90
91         if (device_fd < 0)
92           status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
93         else if (backendDrainOutput(print_fd, device_fd))
94           status = CUPS_SC_STATUS_IO_ERROR;
95         else 
96           status = CUPS_SC_STATUS_OK;
97
98         datalen = 0;
99         break;
100
101     case CUPS_SC_CMD_GET_BIDI :
102         status  = CUPS_SC_STATUS_OK;
103         data[0] = use_bc;
104         datalen = 1;
105         break;
106
107     case CUPS_SC_CMD_SNMP_GET :
108     case CUPS_SC_CMD_SNMP_GET_NEXT :
109         fprintf(stderr, "DEBUG: CUPS_SC_CMD_SNMP_%s: %d (%s)\n",
110                 command == CUPS_SC_CMD_SNMP_GET ? "GET" : "GET_NEXT", datalen,
111                 data);
112
113         if (datalen < 2)
114         {
115           status  = CUPS_SC_STATUS_BAD_MESSAGE;
116           datalen = 0;
117           break;
118         }
119
120         if (snmp_fd >= 0)
121         {
122           cups_snmp_t   packet;         /* Packet from printer */
123
124
125           if (!_cupsSNMPStringToOID(data, packet.object_name, CUPS_SNMP_MAX_OID))
126           {
127             status  = CUPS_SC_STATUS_BAD_MESSAGE;
128             datalen = 0;
129             break;
130           }
131
132           status  = CUPS_SC_STATUS_IO_ERROR;
133           datalen = 0;
134
135           if (_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
136                              _cupsSNMPDefaultCommunity(),
137                              command == CUPS_SC_CMD_SNMP_GET ?
138                                  CUPS_ASN1_GET_REQUEST :
139                                  CUPS_ASN1_GET_NEXT_REQUEST, 1,
140                              packet.object_name))
141           {
142             if (_cupsSNMPRead(snmp_fd, &packet, 1.0))
143             {
144               char      *dataptr;       /* Pointer into data */
145               int       i;              /* Looping var */
146
147
148               if (!_cupsSNMPOIDToString(packet.object_name, data, sizeof(data)))
149               {
150                 fputs("DEBUG: Bad OID returned!\n", stderr);
151                 break;
152               }
153
154               datalen = (int)strlen(data) + 1;
155               dataptr = data + datalen;
156
157               switch (packet.object_type)
158               {
159                 case CUPS_ASN1_BOOLEAN :
160                     snprintf(dataptr, sizeof(data) - (dataptr - data), "%d",
161                              packet.object_value.boolean);
162                     datalen += (int)strlen(dataptr);
163                     break;
164
165                 case CUPS_ASN1_INTEGER :
166                     snprintf(dataptr, sizeof(data) - (dataptr - data), "%d",
167                              packet.object_value.integer);
168                     datalen += (int)strlen(dataptr);
169                     break;
170
171                 case CUPS_ASN1_BIT_STRING :
172                 case CUPS_ASN1_OCTET_STRING :
173                     if (packet.object_value.string.num_bytes < 0)
174                       i = 0;
175                     else if (packet.object_value.string.num_bytes < 
176                              (sizeof(data) - (dataptr - data)))
177                       i = packet.object_value.string.num_bytes;
178                     else
179                       i = (int)(sizeof(data) - (dataptr - data));
180
181                     memcpy(dataptr, packet.object_value.string.bytes, i);
182
183                     datalen += i;
184                     break;
185
186                 case CUPS_ASN1_OID :
187                     _cupsSNMPOIDToString(packet.object_value.oid, dataptr,
188                                          sizeof(data) - (dataptr - data));
189                     datalen += (int)strlen(dataptr);
190                     break;
191
192                 case CUPS_ASN1_HEX_STRING :
193                     for (i = 0;
194                          i < packet.object_value.string.num_bytes &&
195                              dataptr < (data + sizeof(data) - 3);
196                          i ++, dataptr += 2)
197                       sprintf(dataptr, "%02X",
198                               packet.object_value.string.bytes[i]);
199                     datalen += (int)strlen(dataptr);
200                     break;
201
202                 case CUPS_ASN1_COUNTER :
203                     snprintf(dataptr, sizeof(data) - (dataptr - data), "%d",
204                              packet.object_value.counter);
205                     datalen += (int)strlen(dataptr);
206                     break;
207
208                 case CUPS_ASN1_GAUGE :
209                     snprintf(dataptr, sizeof(data) - (dataptr - data), "%u",
210                              packet.object_value.gauge);
211                     datalen += (int)strlen(dataptr);
212                     break;
213
214                 case CUPS_ASN1_TIMETICKS :
215                     snprintf(dataptr, sizeof(data) - (dataptr - data), "%u",
216                              packet.object_value.timeticks);
217                     datalen += (int)strlen(dataptr);
218                     break;
219
220                 default :
221                     fprintf(stderr, "DEBUG: Unknown OID value type %02X!\n",
222                             packet.object_type);
223
224                 case CUPS_ASN1_NULL_VALUE :
225                     dataptr[0] = '\0';
226                     break;
227               }
228
229               fprintf(stderr, "DEBUG: Returning %s %s\n", data, data + datalen);
230
231               status = CUPS_SC_STATUS_OK;
232             }
233             else
234               fputs("DEBUG: SNMP read error...\n", stderr);
235           }
236           else
237             fputs("DEBUG: SNMP write error...\n", stderr);
238           break;
239         }
240
241         status  = CUPS_SC_STATUS_NOT_IMPLEMENTED;
242         datalen = 0;
243         break;
244
245     case CUPS_SC_CMD_GET_DEVICE_ID :
246         if (snmp_fd >= 0)
247         {
248           cups_snmp_t   packet;         /* Packet from printer */
249           static const int ppmPrinterIEEE1284DeviceId[] =
250                         { CUPS_OID_ppmPrinterIEEE1284DeviceId,1,-1 };
251
252
253           status  = CUPS_SC_STATUS_IO_ERROR;
254           datalen = 0;
255
256           if (_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
257                              _cupsSNMPDefaultCommunity(),
258                              CUPS_ASN1_GET_REQUEST, 1,
259                              ppmPrinterIEEE1284DeviceId))
260           {
261             if (_cupsSNMPRead(snmp_fd, &packet, 1.0) &&
262                 packet.object_type == CUPS_ASN1_OCTET_STRING)
263             {
264               strlcpy(data, (char *)packet.object_value.string.bytes,
265                       sizeof(data));
266               datalen = (int)strlen(data);
267               status  = CUPS_SC_STATUS_OK;
268             }
269           }
270
271           break;
272         }
273
274         if ((device_id = getenv("1284DEVICEID")) != NULL)
275         {
276           strlcpy(data, device_id, sizeof(data));
277           datalen = (int)strlen(data);
278           status  = CUPS_SC_STATUS_OK;
279           break;
280         }
281
282     case CUPS_SC_CMD_GET_CONNECTED :
283         status  = CUPS_SC_STATUS_OK;
284         data[0] = device_fd != -1;
285         datalen = 1;
286         break;
287
288     default :
289         status  = CUPS_SC_STATUS_NOT_IMPLEMENTED;
290         datalen = 0;
291         break;
292   }
293
294   return (cupsSideChannelWrite(command, status, data, datalen, 1.0));
295 }
296
297
298 /*
299  * End of "$Id: network.c 9578 2011-03-04 18:44:47Z mike $".
300  */