/*
- * "$Id: http.c 5023 2006-01-29 14:39:44Z mike $"
+ * "$Id$"
*
* HTTP routines for the Common UNIX Printing System (CUPS).
*
*
* Contents:
*
+ * httpBlocking() - Set blocking/non-blocking behavior on a connection.
* httpCheck() - Check to see if there is a pending response from
* the server.
* httpClearCookie() - Clear the cookie value(s).
+ * httpClearFields() - Clear HTTP request fields.
* httpClose() - Close an HTTP connection...
* httpConnect() - Connect to a HTTP server.
* httpConnectEncrypt() - Connect to a HTTP server using encryption.
* httpDelete() - Send a DELETE request to the server.
* httpEncryption() - Set the required encryption on the link.
+ * httpError() - Get the last error on a connection.
* httpFlush() - Flush data from a HTTP connection.
* httpFlushWrite() - Flush data in write buffer.
* httpGet() - Send a GET request to the server.
+ * httpGetBlocking() - Get the blocking/non-block state of a connection.
+ * httpGetCookie() - Get any cookie data from the response.
+ * httpGetFd() - Get the file descriptor associated with a
+ * connection.
+ * httpGetField() - Get a field value from a request/response.
* httpGetLength() - Get the amount of data remaining from the
* content-length or transfer-encoding fields.
* httpGetLength2() - Get the amount of data remaining from the
* content-length or transfer-encoding fields.
+ * httpGetStatus() - Get the status of the last HTTP request.
* httpGetSubField() - Get a sub-field value.
* httpGets() - Get a line of text from a HTTP connection.
* httpHead() - Send a HEAD request to the server.
* _httpReadCDSA() - Read function for CDSA decryption code.
* httpReconnect() - Reconnect to a HTTP server...
* httpSetCookie() - Set the cookie value(s)...
+ * httpSetExpect() - Set the Expect: header in a request.
* httpSetField() - Set the value of an HTTP header.
* httpSetLength() - Set the content-length and transfer-encoding.
* httpTrace() - Send an TRACE request to the server.
};
+/*
+ * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection.
+ */
+
+void
+httpBlocking(http_t *http, /* I - HTTP connection */
+ int b) /* I - 1 = blocking, 0 = non-blocking */
+{
+ if (http)
+ http->blocking = b;
+}
+
+
/*
* 'httpCheck()' - Check to see if there is a pending response from the server.
*/
-int /* O - 0 = no data, 1 = data available */
-httpCheck(http_t *http) /* I - HTTP connection */
+int /* O - 0 = no data, 1 = data available */
+httpCheck(http_t *http) /* I - HTTP connection */
{
return (httpWait(http, 0));
}
*/
void
-httpClearCookie(http_t *http) /* I - Connection */
+httpClearCookie(http_t *http) /* I - HTTP connection */
{
if (!http)
return;
}
+/*
+ * 'httpClearFields()' - Clear HTTP request fields.
+ */
+
+void
+httpClearFields(http_t *http) /* I - HTTP connection */
+{
+ if (http)
+ {
+ memset(http->fields, 0, sizeof(http->fields));
+ httpSetField(http, HTTP_FIELD_HOST, http->hostname);
+
+ http->expect = (http_status_t)0;
+ }
+}
+
+
/*
* 'httpClose()' - Close an HTTP connection...
*/
void
-httpClose(http_t *http) /* I - Connection to close */
+httpClose(http_t *http) /* I - HTTP connection */
{
DEBUG_printf(("httpClose(http=%p)\n", http));
*/
int /* O - Status of call (0 = success) */
-httpDelete(http_t *http, /* I - HTTP data */
+httpDelete(http_t *http, /* I - HTTP connection */
const char *uri) /* I - URI to delete */
{
return (http_send(http, HTTP_DELETE, uri));
*/
int /* O - -1 on error, 0 on success */
-httpEncryption(http_t *http, /* I - HTTP data */
+httpEncryption(http_t *http, /* I - HTTP connection */
http_encryption_t e) /* I - New encryption preference */
{
DEBUG_printf(("httpEncryption(http=%p, e=%d)\n", http, e));
}
+/*
+ * 'httpError()' - Get the last error on a connection.
+ */
+
+int /* O - Error code (errno) value */
+httpError(http_t *http) /* I - HTTP connection */
+{
+ if (http)
+ return (http->error);
+ else
+ return (EINVAL);
+}
+
+
/*
* 'httpFlush()' - Flush data from a HTTP connection.
*/
void
-httpFlush(http_t *http) /* I - HTTP data */
+httpFlush(http_t *http) /* I - HTTP connection */
{
char buffer[8192]; /* Junk buffer */
int blocking; /* To block or not to block */
*/
int /* O - Bytes written or -1 on error */
-httpFlushWrite(http_t *http) /* I - HTTP data */
+httpFlushWrite(http_t *http) /* I - HTTP connection */
{
int bytes; /* Bytes written */
*/
int /* O - Status of call (0 = success) */
-httpGet(http_t *http, /* I - HTTP data */
+httpGet(http_t *http, /* I - HTTP connection */
const char *uri) /* I - URI to get */
{
return (http_send(http, HTTP_GET, uri));
}
+/*
+ * 'httpGetBlocking()' - Get the blocking/non-block state of a connection.
+ *
+ * @since CUPS 1.2@
+ */
+
+int /* O - 1 if blocking, 0 if non-blocking */
+httpGetBlocking(http_t *http) /* I - HTTP connection */
+{
+ return (http ? http->blocking : 0);
+}
+
+
+/*
+ * 'httpGetCookie()' - Get any cookie data from the response.
+ *
+ * @since CUPS 1.1.19@
+ */
+
+const char * /* O - Cookie data or NULL */
+httpGetCookie(http_t *http) /* I - HTTP connecion */
+{
+ return (http ? http->cookie : NULL);
+}
+
+
+/*
+ * 'httpGetFd()' - Get the file descriptor associated with a connection.
+ *
+ * @since CUPS 1.2@
+ */
+
+int /* O - File descriptor or -1 if none */
+httpGetFd(http_t *http) /* I - HTTP connection */
+{
+ return (http ? http->fd : -1);
+}
+
+
+/*
+ * 'httpGetField()' - Get a field value from a request/response.
+ */
+
+const char * /* O - Field value */
+httpGetField(http_t *http, /* I - HTTP connection */
+ http_field_t field) /* I - Field to get */
+{
+ if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
+ return (NULL);
+ else
+ return (http->fields[field]);
+}
+
+
+/*
+ * 'httpGetLength()' - Get the amount of data remaining from the
+ * content-length or transfer-encoding fields.
+ *
+ * This function is deprecated and will not return lengths larger than
+ * 2^31 - 1; use httpGetLength2() instead.
+ *
+ * @deprecated@
+ */
+
+int /* O - Content length */
+httpGetLength(http_t *http) /* I - HTTP connection */
+{
+ /*
+ * Get the read content length and return the 32-bit value.
+ */
+
+ if (http)
+ {
+ httpGetLength2(http);
+
+ return (http->_data_remaining);
+ }
+ else
+ return (-1);
+}
+
+
+/*
+ * 'httpGetLength2()' - Get the amount of data remaining from the
+ * content-length or transfer-encoding fields.
+ *
+ * This function returns the complete content length, even for
+ * content larger than 2^31 - 1.
+ *
+ * @since CUPS 1.2@
+ */
+
+off_t /* O - Content length */
+httpGetLength2(http_t *http) /* I - HTTP connection */
+{
+ DEBUG_printf(("httpGetLength2(http=%p), state=%d\n", http, http->state));
+
+ if (!http)
+ return (-1);
+
+ if (!strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
+ {
+ DEBUG_puts("httpGetLength2: chunked request!");
+
+ http->data_encoding = HTTP_ENCODE_CHUNKED;
+ http->data_remaining = 0;
+ }
+ else
+ {
+ http->data_encoding = HTTP_ENCODE_LENGTH;
+
+ /*
+ * The following is a hack for HTTP servers that don't send a
+ * content-length or transfer-encoding field...
+ *
+ * If there is no content-length then the connection must close
+ * after the transfer is complete...
+ */
+
+ if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0')
+ http->data_remaining = 2147483647;
+ else
+ http->data_remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
+ NULL, 10);
+
+ DEBUG_printf(("httpGetLength2: content_length=" CUPS_LLFMT "\n",
+ CUPS_LLCAST http->data_remaining));
+ }
+
+ if (http->data_remaining <= INT_MAX)
+ http->_data_remaining = (int)http->data_remaining;
+ else
+ http->_data_remaining = INT_MAX;
+
+ return (http->data_remaining);
+}
+
+
+/*
+ * 'httpGetStatus()' - Get the status of the last HTTP request.
+ *
+ * @since CUPS 1.2@
+ */
+
+http_status_t /* O - HTTP status */
+httpGetStatus(http_t *http) /* I - HTTP connection */
+{
+ return (http ? http->status : HTTP_ERROR);
+}
+
+
/*
* 'httpGetSubField()' - Get a sub-field value.
*
*/
char * /* O - Value or NULL */
-httpGetSubField(http_t *http, /* I - HTTP data */
+httpGetSubField(http_t *http, /* I - HTTP connection */
http_field_t field, /* I - Field index */
const char *name, /* I - Name of sub-field */
char *value) /* O - Value string */
*/
char * /* O - Value or NULL */
-httpGetSubField2(http_t *http, /* I - HTTP data */
+httpGetSubField2(http_t *http, /* I - HTTP connection */
http_field_t field, /* I - Field index */
const char *name, /* I - Name of sub-field */
char *value, /* O - Value string */
http, field, name, value, valuelen));
if (!http || !name || !value || valuelen < 2 ||
- field < HTTP_FIELD_ACCEPT_LANGUAGE ||
- field > HTTP_FIELD_WWW_AUTHENTICATE)
+ field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
return (NULL);
end = value + valuelen - 1;
}
-/*
- * 'httpGetLength()' - Get the amount of data remaining from the
- * content-length or transfer-encoding fields.
- *
- * This function is deprecated and will not return lengths larger than
- * 2^31 - 1; use httpGetLength2() instead.
- *
- * @since CUPS 1.2@
- */
-
-int /* O - Content length */
-httpGetLength(http_t *http) /* I - HTTP data */
-{
- /*
- * Get the read content length and return the 32-bit value.
- */
-
- httpGetLength2(http);
-
- return (http->_data_remaining);
-}
-
-
-/*
- * 'httpGetLength2()' - Get the amount of data remaining from the
- * content-length or transfer-encoding fields.
- *
- * This function returns the complete content length, even for
- * content larger than 2^31 - 1.
- */
-
-off_t /* O - Content length */
-httpGetLength2(http_t *http) /* I - HTTP data */
-{
- DEBUG_printf(("httpGetLength2(http=%p), state=%d\n", http, http->state));
-
- if (!strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
- {
- DEBUG_puts("httpGetLength2: chunked request!");
-
- http->data_encoding = HTTP_ENCODE_CHUNKED;
- http->data_remaining = 0;
- }
- else
- {
- http->data_encoding = HTTP_ENCODE_LENGTH;
-
- /*
- * The following is a hack for HTTP servers that don't send a
- * content-length or transfer-encoding field...
- *
- * If there is no content-length then the connection must close
- * after the transfer is complete...
- */
-
- if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0')
- http->data_remaining = 2147483647;
- else
- http->data_remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
- NULL, 10);
-
- DEBUG_printf(("httpGetLength2: content_length=" CUPS_LLFMT "\n",
- CUPS_LLCAST http->data_remaining));
- }
-
- if (http->data_remaining <= INT_MAX)
- http->_data_remaining = (int)http->data_remaining;
- else
- http->_data_remaining = INT_MAX;
-
- return (http->data_remaining);
-}
-
-
/*
* 'httpGets()' - Get a line of text from a HTTP connection.
*/
char * /* O - Line or NULL */
httpGets(char *line, /* I - Line to read into */
int length, /* I - Max length of buffer */
- http_t *http) /* I - HTTP data */
+ http_t *http) /* I - HTTP connection */
{
char *lineptr, /* Pointer into line */
*lineend, /* End of line */
*/
if (!http->blocking && !http_wait(http, 1000))
+ {
+ DEBUG_puts("httpGets: Timed out!");
+ http->error = ETIMEDOUT;
return (NULL);
+ }
#ifdef HAVE_SSL
if (http->tls)
*/
int /* O - Status of call (0 = success) */
-httpHead(http_t *http, /* I - HTTP data */
+httpHead(http_t *http, /* I - HTTP connection */
const char *uri) /* I - URI for head */
{
return (http_send(http, HTTP_HEAD, uri));
*/
int /* O - Status of call (0 = success) */
-httpOptions(http_t *http, /* I - HTTP data */
+httpOptions(http_t *http, /* I - HTTP connection */
const char *uri) /* I - URI for options */
{
return (http_send(http, HTTP_OPTIONS, uri));
*/
int /* O - Status of call (0 = success) */
-httpPost(http_t *http, /* I - HTTP data */
+httpPost(http_t *http, /* I - HTTP connection */
const char *uri) /* I - URI for post */
{
return (http_send(http, HTTP_POST, uri));
/*
* 'httpPrintf()' - Print a formatted string to a HTTP connection.
+ *
+ * @private@
*/
int /* O - Number of bytes written */
-httpPrintf(http_t *http, /* I - HTTP data */
+httpPrintf(http_t *http, /* I - HTTP connection */
const char *format, /* I - printf-style format string */
...) /* I - Additional args as needed */
{
*/
int /* O - Status of call (0 = success) */
-httpPut(http_t *http, /* I - HTTP data */
+httpPut(http_t *http, /* I - HTTP connection */
const char *uri) /* I - URI to put */
{
return (http_send(http, HTTP_PUT, uri));
*/
int /* O - Number of bytes read */
-httpRead(http_t *http, /* I - HTTP data */
+httpRead(http_t *http, /* I - HTTP connection */
char *buffer, /* I - Buffer for data */
int length) /* I - Maximum number of bytes */
{
/*
* 'httpRead2()' - Read data from a HTTP connection.
+ *
+ * @since CUPS 1.2@
*/
ssize_t /* O - Number of bytes read */
-httpRead2(http_t *http, /* I - HTTP data */
+httpRead2(http_t *http, /* I - HTTP connection */
char *buffer, /* I - Buffer for data */
size_t length) /* I - Maximum number of bytes */
{
void *data, /* I - Data buffer */
size_t *dataLength) /* IO - Number of bytes */
{
- OSStatus result; /* Return value */
- ssize_t bytes; /* Number of bytes read */
+ OSStatus result; /* Return value */
+ ssize_t bytes; /* Number of bytes read */
+ cdsa_conn_ref_t u; /* Connection reference union */
- for (;;)
- {
- bytes = recv((int)connection, data, *dataLength, 0);
+ u.connection = connection;
- if (bytes > 0)
- {
- result = (bytes == *dataLength);
- *dataLength = bytes;
+ do
+ bytes = recv(u.sock, data, *dataLength, 0);
+ while (bytes == -1 && errno == EINTR);
- return (result);
- }
+ if (bytes == *dataLength)
+ result = 0;
+ else if (bytes > 0)
+ {
+ *dataLength = bytes;
+ result = errSSLWouldBlock;
+ }
+ else
+ {
+ *dataLength = 0;
if (bytes == 0)
- return (errSSLClosedAbort);
-
- if (errno == EAGAIN)
- return (errSSLWouldBlock);
-
- if (errno == EPIPE)
- return (errSSLClosedAbort);
-
- if (errno != EINTR)
- return (errSSLInternal);
+ result = errSSLClosedAbort;
+ else if (errno == EAGAIN)
+ result = errSSLWouldBlock;
+ else if (errno == EPIPE)
+ result = errSSLClosedAbort;
+ else
+ result = errSSLInternal;
}
+
+ return result;
}
#endif /* HAVE_SSL && HAVE_CDSASSL */
/*
- * 'httpReconnect()' - Reconnect to a HTTP server...
+ * 'httpReconnect()' - Reconnect to a HTTP server.
*/
int /* O - 0 on success, non-zero on failure */
-httpReconnect(http_t *http) /* I - HTTP data */
+httpReconnect(http_t *http) /* I - HTTP connection */
{
http_addrlist_t *addr; /* Connected address */
*/
if (http->fd >= 0)
+ {
#ifdef WIN32
closesocket(http->fd);
#else
close(http->fd);
#endif /* WIN32 */
+ http->fd = -1;
+ }
+
/*
* Connect to the server...
*/
}
+/*
+ * 'httpSetExpect()' - Set the Expect: header in a request.
+ *
+ * Currently only HTTP_CONTINUE is supported for the "expect" argument.
+ *
+ * @since CUPS 1.2@
+ */
+
+void
+httpSetExpect(http_t *http, /* I - HTTP connection */
+ http_status_t expect) /* I - HTTP status to expect (HTTP_CONTINUE) */
+{
+ if (http)
+ http->expect = expect;
+}
+
+
/*
* 'httpSetField()' - Set the value of an HTTP header.
*/
void
-httpSetField(http_t *http, /* I - HTTP data */
+httpSetField(http_t *http, /* I - HTTP connection */
http_field_t field, /* I - Field index */
const char *value) /* I - Value */
{
*/
void
-httpSetLength(http_t *http, /* I - HTTP data */
+httpSetLength(http_t *http, /* I - HTTP connection */
size_t length) /* I - Length (0 for chunked) */
{
if (!http)
*/
int /* O - Status of call (0 = success) */
-httpTrace(http_t *http, /* I - HTTP data */
+httpTrace(http_t *http, /* I - HTTP connection */
const char *uri) /* I - URI for trace */
{
return (http_send(http, HTTP_TRACE, uri));
*/
http_status_t /* O - HTTP status */
-httpUpdate(http_t *http) /* I - HTTP data */
+httpUpdate(http_t *http) /* I - HTTP connection */
{
char line[32768], /* Line from connection... */
*value; /* Pointer to value on line */
case HTTP_PUT :
http->state ++;
case HTTP_POST_SEND :
+ case HTTP_HEAD :
break;
default :
*/
int /* O - 1 if data is available, 0 otherwise */
-httpWait(http_t *http, /* I - HTTP data */
+httpWait(http_t *http, /* I - HTTP connection */
int msec) /* I - Milliseconds to wait */
{
/*
*/
int /* O - Number of bytes written */
-httpWrite(http_t *http, /* I - HTTP data */
+httpWrite(http_t *http, /* I - HTTP connection */
const char *buffer, /* I - Buffer for data */
int length) /* I - Number of bytes to write */
{
/*
* 'httpWrite2()' - Write data to a HTTP connection.
+ *
+ * @since CUPS 1.2@
*/
ssize_t /* O - Number of bytes written */
-httpWrite2(http_t *http, /* I - HTTP data */
+httpWrite2(http_t *http, /* I - HTTP connection */
const char *buffer, /* I - Buffer for data */
size_t length) /* I - Number of bytes to write */
{
const void *data, /* I - Data buffer */
size_t *dataLength) /* IO - Number of bytes */
{
- OSStatus result; /* Return value */
- ssize_t bytes; /* Number of bytes read */
+ OSStatus result; /* Return value */
+ ssize_t bytes; /* Number of bytes read */
+ cdsa_conn_ref_t u; /* Connection reference union */
- for (;;)
- {
- bytes = write((int)connection, data, *dataLength);
-
- if (bytes >= 0)
- {
- result = (bytes == *dataLength) ? 0 : errSSLWouldBlock;
- *dataLength = bytes;
+ u.connection = connection;
- return (result);
- }
+ do
+ bytes = write(u.sock, data, *dataLength);
+ while (bytes == -1 && errno == EINTR);
+ if (bytes == *dataLength)
+ result = 0;
+ else if (bytes >= 0)
+ {
+ *dataLength = bytes;
+ result = errSSLWouldBlock;
+ }
+ else
+ {
+ *dataLength = 0;
+
if (errno == EAGAIN)
- return (errSSLWouldBlock);
-
- if (errno == EPIPE)
- return (errSSLClosedAbort);
-
- if (errno != EINTR)
- return (errSSLInternal);
+ result = errSSLWouldBlock;
+ else if (errno == EPIPE)
+ result = errSSLClosedAbort;
+ else
+ result = errSSLInternal;
}
+
+ return result;
}
#endif /* HAVE_SSL && HAVE_CDSASSL */
*/
static int /* O - Bytes read */
-http_read_ssl(http_t *http, /* I - HTTP data */
+http_read_ssl(http_t *http, /* I - HTTP connection */
char *buf, /* I - Buffer to store data */
int len) /* I - Length of buffer */
{
size_t processed; /* Number of bytes processed */
- error = SSLRead((SSLContextRef)http->tls, buf, len, &processed);
+ error = SSLRead(((http_tls_t *)http->tls)->session, buf, len, &processed);
switch (error)
{
result = 0;
break;
case errSSLWouldBlock :
- errno = EAGAIN;
- result = -1;
+ if (processed)
+ result = (int)processed;
+ else
+ {
+ result = -1;
+ errno = EINTR;
+ }
break;
default :
errno = EPIPE;
*/
static int /* O - 0 on success, non-zero on error */
-http_send(http_t *http, /* I - HTTP data */
+http_send(http_t *http, /* I - HTTP connection */
http_state_t request, /* I - Request code */
const char *uri) /* I - URI */
{
return (-1);
}
+ if (http->expect == HTTP_CONTINUE &&
+ (http->state == HTTP_POST_RECV || http->state == HTTP_PUT_RECV))
+ if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
+ {
+ http->status = HTTP_ERROR;
+ return (-1);
+ }
+
if (httpPrintf(http, "\r\n") < 1)
{
http->status = HTTP_ERROR;
*/
static int /* O - Status of connection */
-http_setup_ssl(http_t *http) /* I - HTTP data */
+http_setup_ssl(http_t *http) /* I - HTTP connection */
{
# ifdef HAVE_LIBSSL
- SSL_CTX *context; /* Context for encryption */
- SSL *conn; /* Connection for encryption */
+ SSL_CTX *context; /* Context for encryption */
+ SSL *conn; /* Connection for encryption */
# elif defined(HAVE_GNUTLS)
- http_tls_t *conn; /* TLS session object */
+ http_tls_t *conn; /* TLS session object */
gnutls_certificate_client_credentials *credentials;
- /* TLS credentials */
+ /* TLS credentials */
# elif defined(HAVE_CDSASSL)
- SSLContextRef conn; /* Context for encryption */
- OSStatus error; /* Error info */
+ OSStatus error; /* Error code */
+ http_tls_t *conn; /* CDSA connection information */
+ cdsa_conn_ref_t u; /* Connection reference union */
# endif /* HAVE_LIBSSL */
}
# elif defined(HAVE_GNUTLS)
- conn = (http_tls_t *)malloc(sizeof(http_tls_t));
-
- if (conn == NULL)
+ if ((conn = (http_tls_t *)malloc(sizeof(http_tls_t))) == NULL)
{
http->error = errno;
http->status = HTTP_ERROR;
gnutls_init(&(conn->session), GNUTLS_CLIENT);
gnutls_set_default_priority(conn->session);
gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
- gnutls_transport_set_ptr(conn->session, http->fd);
+ gnutls_transport_set_ptr(conn->session,
+ (gnutls_transport_ptr)((long)http->fd));
if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
{
conn->credentials = credentials;
# elif defined(HAVE_CDSASSL)
- error = SSLNewContext(false, &conn);
+ conn = (http_tls_t *)calloc(1, sizeof(http_tls_t));
- if (!error)
- error = SSLSetIOFuncs(conn, _httpReadCDSA, _httpWriteCDSA);
+ if (conn == NULL)
+ return (-1);
+
+ if ((error = SSLNewContext(false, &conn->session)))
+ {
+ http->error = error;
+ http->status = HTTP_ERROR;
+
+ free(conn);
+ return (-1);
+ }
+
+ /*
+ * Use a union to resolve warnings about int/pointer size mismatches...
+ */
+
+ u.connection = NULL;
+ u.sock = http->fd;
+ error = SSLSetConnection(conn->session, u.connection);
if (!error)
- error = SSLSetConnection(conn, (SSLConnectionRef)http->fd);
+ error = SSLSetIOFuncs(conn->session, _httpReadCDSA, _httpWriteCDSA);
if (!error)
- error = SSLSetAllowsExpiredCerts(conn, true);
+ error = SSLSetAllowsExpiredCerts(conn->session, true);
if (!error)
- error = SSLSetAllowsAnyRoot(conn, true);
+ error = SSLSetAllowsAnyRoot(conn->session, true);
if (!error)
- error = SSLHandshake(conn);
+ {
+ while ((error = SSLHandshake(conn->session)) == errSSLWouldBlock)
+ usleep(1000);
+ }
- if (error != 0)
+ if (error)
{
http->error = error;
http->status = HTTP_ERROR;
- SSLDisposeContext(conn);
+ SSLDisposeContext(conn->session);
- close(http->fd);
+ free(conn);
return (-1);
}
*/
static void
-http_shutdown_ssl(http_t *http) /* I - HTTP data */
+http_shutdown_ssl(http_t *http) /* I - HTTP connection */
{
# ifdef HAVE_LIBSSL
- SSL_CTX *context; /* Context for encryption */
- SSL *conn; /* Connection for encryption */
+ SSL_CTX *context; /* Context for encryption */
+ SSL *conn; /* Connection for encryption */
conn = (SSL *)(http->tls);
SSL_free(conn);
# elif defined(HAVE_GNUTLS)
- http_tls_t *conn; /* Encryption session */
+ http_tls_t *conn; /* Encryption session */
gnutls_certificate_client_credentials *credentials;
- /* TLS credentials */
+ /* TLS credentials */
conn = (http_tls_t *)(http->tls);
free(conn);
# elif defined(HAVE_CDSASSL)
- SSLClose((SSLContextRef)http->tls);
- SSLDisposeContext((SSLContextRef)http->tls);
+ http_tls_t *conn; /* CDSA connection information */
+
+
+ conn = (http_tls_t *)(http->tls);
+
+ while (SSLClose(conn->session) == errSSLWouldBlock)
+ usleep(1000);
+
+ SSLDisposeContext(conn->session);
+
+ if (conn->certsArray)
+ CFRelease(conn->certsArray);
+
+ free(conn);
# endif /* HAVE_LIBSSL */
http->tls = NULL;
* 'http_upgrade()' - Force upgrade to TLS encryption.
*/
-static int /* O - Status of connection */
-http_upgrade(http_t *http) /* I - HTTP data */
+static int /* O - Status of connection */
+http_upgrade(http_t *http) /* I - HTTP connection */
{
- int ret; /* Return value */
- http_t myhttp; /* Local copy of HTTP data */
+ int ret; /* Return value */
+ http_t myhttp; /* Local copy of HTTP data */
DEBUG_printf(("http_upgrade(%p)\n", http));
*/
static int /* O - 1 if data is available, 0 otherwise */
-http_wait(http_t *http, /* I - HTTP data */
+http_wait(http_t *http, /* I - HTTP connection */
int msec) /* I - Milliseconds to wait */
{
#ifndef WIN32
# elif defined(HAVE_CDSASSL)
size_t bytes; /* Bytes that are available */
- if (!SSLGetBufferedReadSize((SSLContextRef)http->tls, &bytes) && bytes > 0)
+ if (!SSLGetBufferedReadSize(((http_tls_t *)http->tls)->session, &bytes) && bytes > 0)
return (1);
# endif /* HAVE_LIBSSL */
}
{
FD_SET(http->fd, http->input_set);
+ DEBUG_printf(("http_wait: msec=%d, http->fd=%d\n", msec, http->fd));
+
if (msec >= 0)
{
timeout.tv_sec = msec / 1000;
}
else
nfds = select(http->fd + 1, http->input_set, NULL, NULL, NULL);
+
+ DEBUG_printf(("http_wait: select() returned %d...\n", nfds));
}
#ifdef WIN32
while (nfds < 0 && WSAGetLastError() == WSAEINTR);
FD_CLR(http->fd, http->input_set);
+ DEBUG_printf(("http_wait: returning with nfds=%d...\n", nfds));
+
return (nfds > 0);
}
*/
static int /* O - Number of bytes written */
-http_write(http_t *http, /* I - HTTP data */
+http_write(http_t *http, /* I - HTTP connection */
const char *buffer, /* I - Buffer for data */
int length) /* I - Number of bytes to write */
{
*/
static int /* O - Number bytes written */
-http_write_chunk(http_t *http, /* I - HTTP data */
+http_write_chunk(http_t *http, /* I - HTTP connection */
const char *buffer, /* I - Buffer to write */
int length) /* I - Length of buffer */
{
*/
static int /* O - Bytes written */
-http_write_ssl(http_t *http, /* I - HTTP data */
+http_write_ssl(http_t *http, /* I - HTTP connection */
const char *buf, /* I - Buffer holding data */
int len) /* I - Length of buffer */
{
size_t processed; /* Number of bytes processed */
- error = SSLWrite((SSLContextRef)http->tls, buf, len, &processed);
+ error = SSLWrite(((http_tls_t *)http->tls)->session, buf, len, &processed);
switch (error)
{
result = 0;
break;
case errSSLWouldBlock :
- errno = EAGAIN;
- result = -1;
+ if (processed)
+ result = (int)processed;
+ else
+ {
+ result = -1;
+ errno = EINTR;
+ }
break;
default :
errno = EPIPE;
/*
- * End of "$Id: http.c 5023 2006-01-29 14:39:44Z mike $".
+ * End of "$Id$".
*/