int blocking) /* I - 1 if the connection should be
blocking, 0 otherwise */
{
- (void)fd;
- (void)blocking;
+ http_t *http; /* HTTP connection */
+ http_addrlist_t addrlist; /* Dummy address list */
+ socklen_t addrlen; /* Length of address */
+ int val; /* Socket option value */
- return (NULL);
+
+ /*
+ * Range check input...
+ */
+
+ if (fd < 0)
+ return (NULL);
+
+ /*
+ * Create the client connection...
+ */
+
+ memset(&addrlist, 0, sizeof(addrlist));
+
+ if ((http = _httpCreate(NULL, 0, &addrlist, AF_UNSPEC,
+ HTTP_ENCRYPTION_IF_REQUESTED, blocking,
+ _HTTP_MODE_SERVER)) == NULL)
+ return (NULL);
+
+ /*
+ * Accept the client and get the remote address...
+ */
+
+ addrlen = sizeof(http_addr_t);
+
+ if ((http->fd = accept(fd, (struct sockaddr *)&(http->addrlist->addr),
+ &addrlen)) < 0)
+ {
+ _cupsSetHTTPError(HTTP_STATUS_ERROR);
+ httpClose(http);
+
+ return (NULL);
+ }
+
+ httpAddrString(&(http->addrlist->addr), http->hostname,
+ sizeof(http->hostname));
+
+#ifdef SO_NOSIGPIPE
+ /*
+ * Disable SIGPIPE for this socket.
+ */
+
+ val = 1;
+ setsockopt(http->fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val));
+#endif /* SO_NOSIGPIPE */
+
+ /*
+ * Using TCP_NODELAY improves responsiveness, especially on systems
+ * with a slow loopback interface. Since we write large buffers
+ * when sending print files and requests, there shouldn't be any
+ * performance penalty for this...
+ */
+
+ val = 1;
+ setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+
+#ifdef FD_CLOEXEC
+ /*
+ * Close this socket when starting another process...
+ */
+
+ fcntl(http->fd, F_SETFD, FD_CLOEXEC);
+#endif /* FD_CLOEXEC */
+
+ return (http);
}
{
memset(http->fields, 0, sizeof(http->fields));
- if (http->hostname[0] == '/')
- httpSetField(http, HTTP_FIELD_HOST, "localhost");
- else
- httpSetField(http, HTTP_FIELD_HOST, http->hostname);
+ if (http->mode == _HTTP_MODE_CLIENT)
+ {
+ if (http->hostname[0] == '/')
+ httpSetField(http, HTTP_FIELD_HOST, "localhost");
+ else
+ httpSetField(http, HTTP_FIELD_HOST, http->hostname);
+ }
if (http->field_authorization)
{
"encryption=%d, blocking=%d, mode=%d)", host, port, addrlist,
family, encryption, blocking, mode));
- if (!host)
+ if (!host && mode == _HTTP_MODE_CLIENT)
return (NULL);
httpInitialize();
#endif /* HAVE_GSSAPI */
http->version = HTTP_VERSION_1_1;
- strlcpy(http->hostname, host, sizeof(http->hostname));
+ if (host)
+ strlcpy(http->hostname, host, sizeof(http->hostname));
if (port == 443) /* Always use encryption for https */
- http->encryption = HTTP_ENCRYPT_ALWAYS;
+ http->encryption = HTTP_ENCRYPTION_ALWAYS;
else
http->encryption = encryption;
bytes = vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
- DEBUG_printf(("3httpPrintf: %s", buf));
+ DEBUG_printf(("3httpPrintf: (%d bytes) %s", bytes, buf));
if (http->data_encoding == HTTP_ENCODING_FIELDS)
return (httpWrite2(http, buf, bytes));
* Range check input...
*/
+ DEBUG_printf(("httpReadRequest(http=%p, uri=%p, urilen=" CUPS_LLFMT ")",
+ http, uri, CUPS_LLCAST urilen));
+
if (uri)
*uri = '\0';
if (!http || !uri || urilen < 1 || http->state != HTTP_STATE_WAITING)
+ {
+ DEBUG_puts("1httpReadRequest: Returning HTTP_STATE_ERROR");
return (HTTP_STATE_ERROR);
+ }
/*
* Reset state...
*/
if (!httpGets(line, sizeof(line), http))
+ {
+ DEBUG_puts("1httpReadRequest: Unable to read, returning HTTP_STATE_ERROR");
return (HTTP_STATE_ERROR);
+ }
if (!line[0])
- return (HTTP_WAITING);
+ {
+ DEBUG_puts("1httpReadRequest: Blank line, returning HTTP_STATE_WAITING");
+ return (HTTP_STATE_WAITING);
+ }
+
+ DEBUG_printf(("1httpReadRequest: %s", line));
/*
* Parse it...
req_uri ++;
if (!*req_uri)
+ {
+ DEBUG_puts("1httpReadRequest: No request URI.");
return (HTTP_STATE_ERROR);
+ }
*req_uri++ = '\0';
req_version ++;
if (!*req_version)
+ {
+ DEBUG_puts("1httpReadRequest: No request protocol version.");
return (HTTP_STATE_ERROR);
+ }
*req_version++ = '\0';
else if (!strcmp(req_method, "CONNECT"))
http->state = HTTP_STATE_CONNECT;
else
+ {
+ DEBUG_printf(("1httpReadRequest: Unknown method \"%s\".", req_method));
return (HTTP_STATE_UNKNOWN_METHOD);
+ }
if (!strcmp(req_version, "HTTP/1.0"))
{
http->keep_alive = HTTP_KEEPALIVE_ON;
}
else
+ {
+ DEBUG_printf(("1httpReadRequest: Unknown version \"%s\".", req_version));
return (HTTP_STATE_UNKNOWN_VERSION);
+ }
+ DEBUG_printf(("1httpReadRequest: URI is %s, returning %d.", req_uri,
+ http->state));
strlcpy(uri, req_uri, urilen);
return (http->state);
* Range check input...
*/
- if (http == NULL || buffer == NULL)
+ if (!http || !buffer)
+ {
+ DEBUG_puts("1httpWrite2: Returning -1 due to bad input.");
return (-1);
+ }
/*
* Mark activity on the connection...
#ifdef HAVE_LIBZ
if (http->coding)
{
+ DEBUG_printf(("1httpWrite2: http->coding=%d", http->coding));
+
if (length == 0)
{
http_content_coding_finish(http);
while (deflate(&(http->stream), Z_NO_FLUSH) == Z_OK)
{
+ http->wused = sizeof(http->wbuffer) - http->stream.avail_out;
+
if (httpFlushWrite(http) < 0)
+ {
+ DEBUG_puts("1httpWrite2: Unable to flush, returning -1.");
return (-1);
+ }
http->stream.next_out = (Bytef *)http->wbuffer;
http->stream.avail_out = sizeof(http->wbuffer);
}
}
+ DEBUG_printf(("1httpWrite2: Returning " CUPS_LLFMT ".", CUPS_LLCAST bytes));
+
return (bytes);
}
* Range check input...
*/
+ DEBUG_printf(("httpWriteResponse(http=%p, status=%d)", http, status));
+
if (!http || status < HTTP_CONTINUE)
+ {
+ DEBUG_puts("1httpWriteResponse: Bad input.");
return (-1);
+ }
/*
* Set the various standard fields if they aren't already...
_http_coding_t coding; /* Content coding value */
+ DEBUG_printf(("http_content_coding_start(http=%p, value=\"%s\")", http,
+ value));
+
if (http->coding != _HTTP_CODING_IDENTITY)
+ {
+ DEBUG_printf(("1http_content_coding_start: http->coding already %d.",
+ http->coding));
return;
+ }
else if (!strcmp(value, "x-gzip") || !strcmp(value, "gzip"))
{
if (http->state == HTTP_GET_SEND || http->state == HTTP_POST_SEND)
coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_GZIP :
_HTTP_CODING_GUNZIP;
else
+ {
+ DEBUG_puts("1http_content_coding_start: Not doing content coding.");
return;
+ }
}
- else if (!strcmp(value, "x-deflate") || strcmp(value, "deflate"))
+ else if (!strcmp(value, "x-deflate") || !strcmp(value, "deflate"))
{
if (http->state == HTTP_GET_SEND || http->state == HTTP_POST_SEND)
coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_DEFLATE :
coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_DEFLATE :
_HTTP_CODING_INFLATE;
else
+ {
+ DEBUG_puts("1http_content_coding_start: Not doing content coding.");
return;
+ }
}
else
+ {
+ DEBUG_puts("1http_content_coding_start: Not doing content coding.");
return;
+ }
memset(&(http->stream), 0, sizeof(http->stream));
}
http->coding = coding;
+
+ DEBUG_printf(("1http_content_coding_start: http->coding now %d.",
+ http->coding));
}
#endif /* HAVE_LIBZ */
typedef struct _ipp_client_s /**** Client data ****/
{
- http_t http; /* HTTP connection */
+ http_t *http; /* HTTP connection */
ipp_t *request, /* IPP request */
*response; /* IPP response */
time_t start; /* Request start time */
ipp_op_t operation_id; /* IPP operation-id */
char uri[1024]; /* Request URI */
http_addr_t addr; /* Client address */
+ char hostname[256]; /* Client hostname */
_ipp_printer_t *printer; /* Printer */
_ipp_job_t *job; /* Current job, if any */
} _ipp_client_t;
int sock) /* I - Listen socket */
{
_ipp_client_t *client; /* Client */
- int val; /* Parameter value */
- socklen_t addrlen; /* Length of address */
if ((client = calloc(1, sizeof(_ipp_client_t))) == NULL)
return (NULL);
}
- client->printer = printer;
- client->http.activity = time(NULL);
- client->http.hostaddr = &(client->addr);
- client->http.blocking = 1;
- client->http.wait_value = 60000;
+ client->printer = printer;
/*
* Accept the client and get the remote address...
*/
- addrlen = sizeof(http_addr_t);
-
- if ((client->http.fd = accept(sock, (struct sockaddr *)&(client->addr),
- &addrlen)) < 0)
+ if ((client->http = httpAcceptConnection(sock, 1)) == NULL)
{
perror("Unable to accept client connection");
return (NULL);
}
- httpAddrString(&(client->addr), client->http.hostname,
- sizeof(client->http.hostname));
+ httpGetHostname(client->http, client->hostname, sizeof(client->hostname));
if (Verbosity)
- fprintf(stderr, "Accepted connection from %s (%s)\n", client->http.hostname,
- client->http.hostaddr->addr.sa_family == AF_INET ? "IPv4" : "IPv6");
-
- /*
- * Using TCP_NODELAY improves responsiveness, especially on systems
- * with a slow loopback interface. Since we write large buffers
- * when sending print files and requests, there shouldn't be any
- * performance penalty for this...
- */
-
- val = 1;
- setsockopt(client->http.fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val,
- sizeof(val));
+ fprintf(stderr, "Accepted connection from %s\n", client->hostname);
return (client);
}
delete_client(_ipp_client_t *client) /* I - Client */
{
if (Verbosity)
- fprintf(stderr, "Closing connection from %s (%s)\n", client->http.hostname,
- client->http.hostaddr->addr.sa_family == AF_INET ? "IPv4" : "IPv6");
+ fprintf(stderr, "Closing connection from %s\n", client->hostname);
/*
* Flush pending writes before closing...
*/
- httpFlushWrite(&(client->http));
-
- if (client->http.fd >= 0)
- close(client->http.fd);
+ httpFlushWrite(client->http);
/*
* Free memory...
*/
- httpClearCookie(&(client->http));
- httpClearFields(&(client->http));
+ httpClose(client->http);
ippDelete(client->request);
-
ippDelete(client->response);
free(client);
if (*s == '&' || *s == '<')
{
if (s > start)
- httpWrite2(&(client->http), start, s - start);
+ httpWrite2(client->http, start, s - start);
if (*s == '&')
- httpWrite2(&(client->http), "&", 5);
+ httpWrite2(client->http, "&", 5);
else
- httpWrite2(&(client->http), "<", 4);
+ httpWrite2(client->http, "<", 4);
start = s + 1;
}
}
if (s > start)
- httpWrite2(&(client->http), start, s - start);
+ httpWrite2(client->http, start, s - start);
}
if (*format == '%')
{
if (format > start)
- httpWrite2(&(client->http), start, format - start);
+ httpWrite2(client->http, start, format - start);
tptr = tformat;
*tptr++ = *format++;
if (*format == '%')
{
- httpWrite2(&(client->http), "%", 1);
+ httpWrite2(client->http, "%", 1);
format ++;
continue;
}
sprintf(temp, tformat, va_arg(ap, double));
- httpWrite2(&(client->http), temp, strlen(temp));
+ httpWrite2(client->http, temp, strlen(temp));
break;
case 'B' : /* Integer formats */
else
sprintf(temp, tformat, va_arg(ap, int));
- httpWrite2(&(client->http), temp, strlen(temp));
+ httpWrite2(client->http, temp, strlen(temp));
break;
case 'p' : /* Pointer value */
sprintf(temp, tformat, va_arg(ap, void *));
- httpWrite2(&(client->http), temp, strlen(temp));
+ httpWrite2(client->http, temp, strlen(temp));
break;
case 'c' : /* Character or character array */
}
if (format > start)
- httpWrite2(&(client->http), start, format - start);
+ httpWrite2(client->http, start, format - start);
va_end(ap);
}
if (!valid_job_attributes(client))
{
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
* Do we have a file to print?
*/
- if (client->http.state == HTTP_POST_RECV)
+ if (client->http->state == HTTP_POST_RECV)
{
respond_ipp(client, IPP_BAD_REQUEST,
"Unexpected document data following request.");
if ((attr = ippFindAttribute(client->request, "which-jobs",
IPP_TAG_KEYWORD)) != NULL)
- fprintf(stderr, "%s Get-Jobs which-jobs=%s", client->http.hostname,
+ fprintf(stderr, "%s Get-Jobs which-jobs=%s", client->http->hostname,
attr->values[0].string.text);
if (!attr || !strcmp(attr->values[0].string.text, "not-completed"))
{
limit = attr->values[0].integer;
- fprintf(stderr, "%s Get-Jobs limit=%d", client->http.hostname, limit);
+ fprintf(stderr, "%s Get-Jobs limit=%d", client->http->hostname, limit);
}
else
limit = 0;
{
first_job_id = attr->values[0].integer;
- fprintf(stderr, "%s Get-Jobs first-job-id=%d", client->http.hostname,
+ fprintf(stderr, "%s Get-Jobs first-job-id=%d", client->http->hostname,
first_job_id);
}
else
if ((attr = ippFindAttribute(client->request, "my-jobs",
IPP_TAG_BOOLEAN)) != NULL)
{
- fprintf(stderr, "%s Get-Jobs my-jobs=%s\n", client->http.hostname,
+ fprintf(stderr, "%s Get-Jobs my-jobs=%s\n", client->http->hostname,
attr->values[0].boolean ? "true" : "false");
if (attr->values[0].boolean)
username = attr->values[0].string.text;
fprintf(stderr, "%s Get-Jobs requesting-user-name=\"%s\"\n",
- client->http.hostname, username);
+ client->http->hostname, username);
}
}
if (!valid_job_attributes(client))
{
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
* Do we have a file to print?
*/
- if (client->http.state == HTTP_POST_SEND)
+ if (client->http->state == HTTP_POST_SEND)
{
respond_ipp(client, IPP_BAD_REQUEST, "No file in request.");
return;
return;
}
- while ((bytes = httpRead2(&(client->http), buffer, sizeof(buffer))) > 0)
+ while ((bytes = httpRead2(client->http, buffer, sizeof(buffer))) > 0)
{
if (write(job->fd, buffer, bytes) < bytes)
{
if (!valid_job_attributes(client))
{
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
* Do we have a file to print?
*/
- if (client->http.state == HTTP_POST_RECV)
+ if (client->http->state == HTTP_POST_RECV)
{
respond_ipp(client, IPP_BAD_REQUEST,
"Unexpected document data following request.");
if ((job = find_job(client)) == NULL)
{
respond_ipp(client, IPP_NOT_FOUND, "Job does not exist.");
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
if (job->state > IPP_JOB_HELD)
{
respond_ipp(client, IPP_NOT_POSSIBLE, "Job is not in a pending state.");
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
else if (job->filename || job->fd >= 0)
{
respond_ipp(client, IPP_MULTIPLE_JOBS_NOT_SUPPORTED,
"Multiple document jobs are not supported.");
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
{
respond_ipp(client, IPP_BAD_REQUEST,
"Missing required last-document attribute.");
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
else if (attr->value_tag != IPP_TAG_BOOLEAN || attr->num_values != 1 ||
!attr->values[0].boolean)
{
respond_unsupported(client, attr);
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
if (!valid_doc_attributes(client))
{
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
return;
}
- while ((bytes = httpRead2(&(client->http), buffer, sizeof(buffer))) > 0)
+ while ((bytes = httpRead2(client->http, buffer, sizeof(buffer))) > 0)
{
if (write(job->fd, buffer, bytes) < bytes)
{
if ((job = find_job(client)) == NULL)
{
respond_ipp(client, IPP_NOT_FOUND, "Job does not exist.");
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
if (job->state > IPP_JOB_HELD)
{
respond_ipp(client, IPP_NOT_POSSIBLE, "Job is not in a pending state.");
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
else if (job->filename || job->fd >= 0)
{
respond_ipp(client, IPP_MULTIPLE_JOBS_NOT_SUPPORTED,
"Multiple document jobs are not supported.");
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
{
respond_ipp(client, IPP_BAD_REQUEST,
"Missing required last-document attribute.");
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
else if (attr->value_tag != IPP_TAG_BOOLEAN || attr->num_values != 1 ||
!attr->values[0].boolean)
{
respond_unsupported(client, attr);
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
if (!valid_doc_attributes(client))
{
- httpFlush(&(client->http));
+ httpFlush(client->http);
return;
}
* Do we have a file to print?
*/
- if (client->http.state == HTTP_POST_RECV)
+ if (client->http->state == HTTP_POST_RECV)
{
respond_ipp(client, IPP_BAD_REQUEST,
"Unexpected document data following request.");
* Loop until we are out of requests or timeout (30 seconds)...
*/
- while (httpWait(&(client->http), 30000))
+ while (httpWait(client->http, 30000))
if (!process_http(client))
break;
* Read a request from the connection...
*/
- while ((http_state = httpReadRequest(&(client->http), uri,
+ while ((http_state = httpReadRequest(client->http, uri,
sizeof(uri))) == HTTP_STATE_WAITING)
usleep(1);
* Parse the request line...
*/
- fprintf(stderr, "%s %s\n", client->http.hostname, uri);
+ fprintf(stderr, "%s %s\n", client->http->hostname, uri);
if (http_state == HTTP_STATE_ERROR)
{
- fprintf(stderr, "%s Bad request line.\n", client->http.hostname);
+ fprintf(stderr, "%s Bad request line.\n", client->http->hostname);
respond_http(client, HTTP_BAD_REQUEST, NULL, 0);
return (0);
}
else if (http_state == HTTP_STATE_UNKNOWN_METHOD)
{
- fprintf(stderr, "%s Bad/unknown operation.\n", client->http.hostname);
+ fprintf(stderr, "%s Bad/unknown operation.\n", client->http->hostname);
respond_http(client, HTTP_BAD_REQUEST, NULL, 0);
return (0);
}
else if (http_state == HTTP_STATE_UNKNOWN_VERSION)
{
- fprintf(stderr, "%s Bad HTTP version.\n", client->http.hostname);
+ fprintf(stderr, "%s Bad HTTP version.\n", client->http->hostname);
respond_http(client, HTTP_BAD_REQUEST, NULL, 0);
return (0);
}
hostname, sizeof(hostname), &port,
client->uri, sizeof(client->uri)) < HTTP_URI_OK)
{
- fprintf(stderr, "%s Bad URI \"%s\".\n", client->http.hostname, uri);
+ fprintf(stderr, "%s Bad URI \"%s\".\n", client->http->hostname, uri);
respond_http(client, HTTP_BAD_REQUEST, NULL, 0);
return (0);
}
*/
client->start = time(NULL);
- client->operation = httpGetState(&(client->http));
+ client->operation = httpGetState(client->http);
/*
* Parse incoming parameters until the status changes...
*/
- while ((http_status = httpUpdate(&(client->http))) == HTTP_STATUS_CONTINUE);
+ while ((http_status = httpUpdate(client->http)) == HTTP_STATUS_CONTINUE);
if (http_status != HTTP_STATUS_OK)
{
return (0);
}
- if (!client->http.fields[HTTP_FIELD_HOST][0] &&
- client->http.version >= HTTP_VERSION_1_1)
+ if (!client->http->fields[HTTP_FIELD_HOST][0] &&
+ client->http->version >= HTTP_VERSION_1_1)
{
/*
* HTTP/1.1 and higher require the "Host:" field...
* Handle HTTP Upgrade...
*/
- if (!_cups_strcasecmp(client->http.fields[HTTP_FIELD_CONNECTION], "Upgrade"))
+ if (!_cups_strcasecmp(client->http->fields[HTTP_FIELD_CONNECTION], "Upgrade"))
{
if (!respond_http(client, HTTP_NOT_IMPLEMENTED, NULL, 0))
return (0);
* Handle HTTP Expect...
*/
- if (client->http.expect &&
+ if (client->http->expect &&
(client->operation == HTTP_STATE_POST ||
client->operation == HTTP_STATE_PUT))
{
- if (client->http.expect == HTTP_STATUS_CONTINUE)
+ if (client->http->expect == HTTP_STATUS_CONTINUE)
{
/*
* Send 100-continue header...
if (!respond_http(client, HTTP_STATUS_EXPECTATION_FAILED, NULL, 0))
return (0);
- httpPrintf(&(client->http), "Content-Length: 0\r\n");
- httpPrintf(&(client->http), "\r\n");
- httpFlushWrite(&(client->http));
- client->http.data_encoding = HTTP_ENCODING_LENGTH;
+ httpPrintf(client->http, "Content-Length: 0\r\n");
+ httpPrintf(client->http, "\r\n");
+ httpFlushWrite(client->http);
+ client->http->data_encoding = HTTP_ENCODING_LENGTH;
}
}
}
while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
- httpWrite2(&(client->http), buffer, bytes);
+ httpWrite2(client->http, buffer, bytes);
- httpFlushWrite(&(client->http));
+ httpFlushWrite(client->http);
close(fd);
}
client->printer->state == IPP_PRINTER_PROCESSING ?
"Printing" : "Stopped",
cupsArrayCount(client->printer->jobs));
- httpWrite2(&(client->http), "", 0);
+ httpWrite2(client->http, "", 0);
return (1);
}
break;
case HTTP_POST :
- if (client->http.data_remaining < 0 ||
- (!client->http.fields[HTTP_FIELD_CONTENT_LENGTH][0] &&
- client->http.data_encoding == HTTP_ENCODING_LENGTH))
+ if (client->http->data_remaining < 0 ||
+ (!client->http->fields[HTTP_FIELD_CONTENT_LENGTH][0] &&
+ client->http->data_encoding == HTTP_ENCODING_LENGTH))
{
/*
* Negative content lengths are invalid...
return (respond_http(client, HTTP_BAD_REQUEST, NULL, 0));
}
- if (strcmp(client->http.fields[HTTP_FIELD_CONTENT_TYPE],
+ if (strcmp(client->http->fields[HTTP_FIELD_CONTENT_TYPE],
"application/ipp"))
{
/*
client->request = ippNew();
- while ((ipp_state = ippRead(&(client->http), client->request)) != IPP_DATA)
+ while ((ipp_state = ippRead(client->http, client->request)) != IPP_DATA)
if (ipp_state == IPP_ERROR)
{
- fprintf(stderr, "%s IPP read error (%s).\n", client->http.hostname,
+ fprintf(stderr, "%s IPP read error (%s).\n", client->http->hostname,
cupsLastErrorString());
respond_http(client, HTTP_STATUS_BAD_REQUEST, NULL, 0);
return (0);
* First build an empty response message for this request...
*/
- client->operation_id = client->request->request.op.operation_id;
- client->response = ippNew();
-
- client->response->request.status.version[0] =
- client->request->request.op.version[0];
- client->response->request.status.version[1] =
- client->request->request.op.version[1];
- client->response->request.status.request_id =
- client->request->request.op.request_id;
+ client->operation_id = ippGetOperation(client->request);
+ client->response = ippNewResponse(client->request);
/*
* Then validate the request header and required attributes...
else
uri = NULL;
- ippAddString(client->response, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
- "attributes-charset", NULL,
- charset ? charset->values[0].string.text : "utf-8");
-
- ippAddString(client->response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
- "attributes-natural-language", NULL,
- language ? language->values[0].string.text : "en");
-
if (charset &&
_cups_strcasecmp(charset->values[0].string.text, "us-ascii") &&
_cups_strcasecmp(charset->values[0].string.text, "utf-8"))
* Try processing the operation...
*/
- if (client->http.expect == HTTP_CONTINUE)
+ if (client->http->expect == HTTP_CONTINUE)
{
/*
* Send 100-continue header...
* Send the HTTP header and return...
*/
- if (client->http.state != HTTP_POST_SEND)
- httpFlush(&(client->http)); /* Flush trailing (junk) data */
+ if (client->http->state != HTTP_POST_SEND)
+ httpFlush(client->http); /* Flush trailing (junk) data */
return (respond_http(client, HTTP_OK, "application/ipp",
ippLength(client->response)));
char message[1024]; /* Text message */
- fprintf(stderr, "%s %s\n", client->http.hostname, httpStatus(code));
+ fprintf(stderr, "%s %s\n", client->http->hostname, httpStatus(code));
- if (code == HTTP_CONTINUE)
+ if (code == HTTP_STATUS_CONTINUE)
{
/*
* 100-continue doesn't send any headers...
*/
- return (httpPrintf(&(client->http), "HTTP/%d.%d 100 Continue\r\n\r\n",
- client->http.version / 100,
- client->http.version % 100) > 0);
+ return (httpWriteResponse(client->http, HTTP_STATUS_CONTINUE) == 0);
}
/*
* Format an error message...
*/
- if (!type && !length && code != HTTP_OK)
+ if (!type && !length && code != HTTP_STATUS_OK)
{
snprintf(message, sizeof(message), "%d - %s\n", code, httpStatus(code));
message[0] = '\0';
/*
- * Send the HTTP status header...
+ * Send the HTTP response header...
*/
- httpFlushWrite(&(client->http));
-
- client->http.data_encoding = HTTP_ENCODING_FIELDS;
-
- if (httpPrintf(&(client->http), "HTTP/%d.%d %d %s\r\n", client->http.version / 100,
- client->http.version % 100, code, httpStatus(code)) < 0)
- return (0);
-
- /*
- * Follow the header with the response fields...
- */
-
- if (httpPrintf(&(client->http), "Date: %s\r\n", httpGetDateString(time(NULL))) < 0)
- return (0);
-
- if (client->http.keep_alive && client->http.version >= HTTP_1_0)
- {
- if (httpPrintf(&(client->http),
- "Connection: Keep-Alive\r\n"
- "Keep-Alive: timeout=10\r\n") < 0)
- return (0);
- }
+ httpClearFields(client->http);
if (code == HTTP_METHOD_NOT_ALLOWED || client->operation == HTTP_OPTIONS)
- {
- if (httpPrintf(&(client->http), "Allow: GET, HEAD, OPTIONS, POST\r\n") < 0)
- return (0);
- }
+ httpSetField(client->http, HTTP_FIELD_ALLOW, "GET, HEAD, OPTIONS, POST");
if (type)
{
if (!strcmp(type, "text/html"))
- {
- if (httpPrintf(&(client->http),
- "Content-Type: text/html; charset=utf-8\r\n") < 0)
- return (0);
- }
- else if (httpPrintf(&(client->http), "Content-Type: %s\r\n", type) < 0)
- return (0);
+ httpSetField(client->http, HTTP_FIELD_CONTENT_TYPE,
+ "text/html; charset=utf-8");
+ else
+ httpSetField(client->http, HTTP_FIELD_CONTENT_TYPE, type);
}
- if (length == 0 && !message[0])
- {
- if (httpPrintf(&(client->http), "Transfer-Encoding: chunked\r\n\r\n") < 0)
- return (0);
- }
- else if (httpPrintf(&(client->http), "Content-Length: " CUPS_LLFMT "\r\n\r\n",
- CUPS_LLCAST length) < 0)
- return (0);
+ httpSetLength(client->http, length);
- if (httpFlushWrite(&(client->http)) < 0)
+ if (httpWriteResponse(client->http, code) < 0)
return (0);
/*
* Send a plain text message.
*/
- if (httpPrintf(&(client->http), "%s", message) < 0)
+ if (httpPrintf(client->http, "%s", message) < 0)
return (0);
}
else if (client->response)
debug_attributes("Response", client->response, 2);
- client->http.data_encoding = HTTP_ENCODING_LENGTH;
- client->http.data_remaining = (off_t)ippLength(client->response);
- client->response->state = IPP_IDLE;
+ client->response->state = IPP_IDLE;
- if (ippWrite(&(client->http), client->response) != IPP_DATA)
+ if (ippWrite(client->http, client->response) != IPP_DATA)
return (0);
}
- else
- client->http.data_encoding = HTTP_ENCODING_CHUNKED;
/*
* Flush the data and return...
*/
- return (httpFlushWrite(&(client->http)) >= 0);
+ return (httpFlushWrite(client->http) >= 0);
}
const char *message, /* I - printf-style status-message */
...) /* I - Additional args as needed */
{
- va_list ap; /* Pointer to additional args */
- char formatted[1024]; /* Formatted errror message */
+ const char *formatted = NULL; /* Formatted message */
- client->response->request.status.status_code = status;
-
- if (!client->response->attrs)
- {
- ippAddString(client->response, IPP_TAG_OPERATION,
- IPP_TAG_CHARSET | IPP_TAG_COPY, "attributes-charset", NULL,
- "utf-8");
- ippAddString(client->response, IPP_TAG_OPERATION,
- IPP_TAG_LANGUAGE | IPP_TAG_COPY, "attributes-natural-language",
- NULL, "en-us");
- }
+ ippSetStatusCode(client->response, status);
if (message)
{
+ va_list ap; /* Pointer to additional args */
+ ipp_attribute_t *attr; /* New status-message attribute */
+
va_start(ap, message);
- vsnprintf(formatted, sizeof(formatted), message, ap);
+ attr = ippAddStringfv(client->response, IPP_TAG_OPERATION, IPP_TAG_TEXT,
+ "status-message", NULL, message, ap);
va_end(ap);
- ippAddString(client->response, IPP_TAG_OPERATION, IPP_TAG_TEXT,
- "status-message", NULL, formatted);
+ formatted = ippGetString(attr, 0, NULL);
}
- else
- formatted[0] = '\0';
- fprintf(stderr, "%s %s %s (%s)\n", client->http.hostname,
- ippOpString(client->operation_id), ippErrorString(status), formatted);
+ if (formatted)
+ fprintf(stderr, "%s %s %s (%s)\n", client->http->hostname,
+ ippOpString(client->operation_id), ippErrorString(status),
+ formatted);
+ else
+ fprintf(stderr, "%s %s %s\n", client->http->hostname,
+ ippOpString(client->operation_id), ippErrorString(status));
}
respond_unsupported(client, attr);
else
fprintf(stderr, "%s %s compression=\"%s\"\n",
- client->http.hostname,
+ client->http->hostname,
ippOpString(client->request->request.op.operation_id),
attr->values[0].string.text);
}
format = attr->values[0].string.text;
fprintf(stderr, "%s %s document-format=\"%s\"\n",
- client->http.hostname,
+ client->http->hostname,
ippOpString(client->request->request.op.operation_id), format);
}
}
unsigned char header[4]; /* First 4 bytes of file */
memset(header, 0, sizeof(header));
- httpPeek(&(client->http), (char *)header, sizeof(header));
+ httpPeek(client->http, (char *)header, sizeof(header));
if (!memcmp(header, "%PDF", 4))
format = "application/pdf";
if (format)
fprintf(stderr, "%s %s Auto-typed document-format=\"%s\"\n",
- client->http.hostname,
+ client->http->hostname,
ippOpString(client->request->request.op.operation_id), format);
if (!attr)