Index: nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c |
diff --git a/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c b/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c |
deleted file mode 100644 |
index 9954f0ca689b0d43bd7b4f8e657fd12559952b72..0000000000000000000000000000000000000000 |
--- a/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c |
+++ /dev/null |
@@ -1,1654 +0,0 @@ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
-/* |
- * pkix_pl_httpdefaultclient.c |
- * |
- * HTTPDefaultClient Function Definitions |
- * |
- */ |
- |
-#include "pkix_pl_httpdefaultclient.h" |
- |
-static void *plContext = NULL; |
- |
-/* |
- * The interface specification for an http client requires that it register |
- * a function table of type SEC_HttpClientFcn, which is defined as a union |
- * of tables, of which only version 1 is defined at present. |
- * |
- * Note: these functions violate the PKIX calling conventions, in that they |
- * return SECStatus rather than PKIX_Error*, and that they do not provide a |
- * plContext argument. They are implemented here as calls to PKIX functions, |
- * but the plContext value is circularly defined - a true kludge. Its value |
- * is saved at the time of the call to pkix_pl_HttpDefaultClient_Create for |
- * subsequent use, but since that initial call comes from the |
- * pkix_pl_HttpDefaultClient_CreateSessionFcn, it's not really getting saved. |
- */ |
-static SEC_HttpClientFcnV1 vtable = { |
- pkix_pl_HttpDefaultClient_CreateSessionFcn, |
- pkix_pl_HttpDefaultClient_KeepAliveSessionFcn, |
- pkix_pl_HttpDefaultClient_FreeSessionFcn, |
- pkix_pl_HttpDefaultClient_RequestCreateFcn, |
- pkix_pl_HttpDefaultClient_SetPostDataFcn, |
- pkix_pl_HttpDefaultClient_AddHeaderFcn, |
- pkix_pl_HttpDefaultClient_TrySendAndReceiveFcn, |
- pkix_pl_HttpDefaultClient_CancelFcn, |
- pkix_pl_HttpDefaultClient_FreeFcn |
-}; |
- |
-static SEC_HttpClientFcn httpClient; |
- |
-static const char *eohMarker = "\r\n\r\n"; |
-static const PKIX_UInt32 eohMarkLen = 4; /* strlen(eohMarker) */ |
-static const char *crlf = "\r\n"; |
-static const PKIX_UInt32 crlfLen = 2; /* strlen(crlf) */ |
-static const char *httpprotocol = "HTTP/"; |
-static const PKIX_UInt32 httpprotocolLen = 5; /* strlen(httpprotocol) */ |
- |
- |
-#define HTTP_UNKNOWN_CONTENT_LENGTH -1 |
- |
-/* --Private-HttpDefaultClient-Functions------------------------- */ |
- |
-/* |
- * FUNCTION: pkix_pl_HttpDefaultClient_HdrCheckComplete |
- * DESCRIPTION: |
- * |
- * This function determines whether the headers in the current receive buffer |
- * in the HttpDefaultClient pointed to by "client" are complete. If so, the |
- * input data is checked for status code, content-type and content-length are |
- * extracted, and the client is set up to read the body of the response. |
- * Otherwise, the client is set up to continue reading header data. |
- * |
- * PARAMETERS: |
- * "client" |
- * The address of the HttpDefaultClient object. Must be non-NULL. |
- * "bytesRead" |
- * The UInt32 number of bytes received in the latest read. |
- * "pKeepGoing" |
- * The address at which the Boolean state machine flag is stored to |
- * indicate whether processing can continue without further input. |
- * Must be non-NULL. |
- * "plContext" |
- * Platform-specific context pointer. |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a HttpDefaultClient Error if the function fails in a |
- * non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_HttpDefaultClient_HdrCheckComplete( |
- PKIX_PL_HttpDefaultClient *client, |
- PKIX_UInt32 bytesRead, |
- PKIX_Boolean *pKeepGoing, |
- void *plContext) |
-{ |
- PKIX_UInt32 alreadyScanned = 0; |
- PKIX_UInt32 comp = 0; |
- PKIX_UInt32 headerLength = 0; |
- PKIX_Int32 contentLength = HTTP_UNKNOWN_CONTENT_LENGTH; |
- char *eoh = NULL; |
- char *statusLineEnd = NULL; |
- char *space = NULL; |
- char *nextHeader = NULL; |
- const char *httpcode = NULL; |
- char *thisHeaderEnd = NULL; |
- char *value = NULL; |
- char *colon = NULL; |
- char *copy = NULL; |
- char *body = NULL; |
- |
- PKIX_ENTER |
- (HTTPDEFAULTCLIENT, |
- "pkix_pl_HttpDefaultClient_HdrCheckComplete"); |
- PKIX_NULLCHECK_TWO(client, pKeepGoing); |
- |
- *pKeepGoing = PKIX_FALSE; |
- |
- /* Does buffer contain end-of-header marker? */ |
- |
- /* Copy number of scanned bytes into a variable. */ |
- alreadyScanned = client->filledupBytes; |
- /* |
- * If this is the initial buffer, we have to scan from the beginning. |
- * If we scanned, failed to find eohMarker, and read some more, we |
- * only have to scan from where we left off. |
- */ |
- if (alreadyScanned > eohMarkLen) { |
- /* Back up and restart scanning over a few bytes that were |
- * scanned before */ |
- PKIX_UInt32 searchStartPos = alreadyScanned - eohMarkLen; |
- eoh = PL_strnstr(&(client->rcvBuf[searchStartPos]), eohMarker, |
- bytesRead + searchStartPos); |
- } else { |
- /* A search from the beginning of the buffer. */ |
- eoh = PL_strnstr(client->rcvBuf, eohMarker, bytesRead); |
- } |
- |
- client->filledupBytes += bytesRead; |
- |
- if (eoh == NULL) { /* did we see end-of-header? */ |
- /* No. Continue to read header data */ |
- client->connectStatus = HTTP_RECV_HDR; |
- *pKeepGoing = PKIX_TRUE; |
- goto cleanup; |
- } |
- |
- /* Yes. Calculate how many bytes in header (not counting eohMarker) */ |
- headerLength = (eoh - client->rcvBuf); |
- |
- /* allocate space to copy header (and for the NULL terminator) */ |
- PKIX_CHECK(PKIX_PL_Malloc(headerLength + 1, (void **)©, plContext), |
- PKIX_MALLOCFAILED); |
- |
- /* copy header data before we corrupt it (by storing NULLs) */ |
- PORT_Memcpy(copy, client->rcvBuf, headerLength); |
- /* Store the NULL terminator */ |
- copy[headerLength] = '\0'; |
- client->rcvHeaders = copy; |
- |
- /* Did caller want a pointer to header? */ |
- if (client->rcv_http_headers != NULL) { |
- /* store pointer for caller */ |
- *(client->rcv_http_headers) = copy; |
- } |
- |
- /* Check that message status is okay. */ |
- statusLineEnd = PL_strnstr(client->rcvBuf, crlf, client->capacity); |
- if (statusLineEnd == NULL) { |
- client->connectStatus = HTTP_ERROR; |
- PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); |
- goto cleanup; |
- } |
- |
- *statusLineEnd = '\0'; |
- |
- space = strchr((const char *)client->rcvBuf, ' '); |
- if (space == NULL) { |
- client->connectStatus = HTTP_ERROR; |
- goto cleanup; |
- } |
- |
- comp = PORT_Strncasecmp((const char *)client->rcvBuf, httpprotocol, |
- httpprotocolLen); |
- if (comp != 0) { |
- client->connectStatus = HTTP_ERROR; |
- goto cleanup; |
- } |
- |
- httpcode = space + 1; |
- space = strchr(httpcode, ' '); |
- if (space == NULL) { |
- client->connectStatus = HTTP_ERROR; |
- goto cleanup; |
- } |
- *space = '\0'; |
- |
- client->responseCode = atoi(httpcode); |
- if (client->responseCode != 200) { |
- client->connectStatus = HTTP_ERROR; |
- goto cleanup; |
- } |
- |
- /* Find the content-type and content-length */ |
- nextHeader = statusLineEnd + crlfLen; |
- *eoh = '\0'; |
- do { |
- thisHeaderEnd = NULL; |
- value = NULL; |
- |
- colon = strchr(nextHeader, ':'); |
- if (colon == NULL) { |
- client->connectStatus = HTTP_ERROR; |
- goto cleanup; |
- } |
- *colon = '\0'; |
- value = colon + 1; |
- if (*value != ' ') { |
- client->connectStatus = HTTP_ERROR; |
- goto cleanup; |
- } |
- value++; |
- thisHeaderEnd = strstr(value, crlf); |
- if (thisHeaderEnd != NULL) { |
- *thisHeaderEnd = '\0'; |
- } |
- comp = PORT_Strcasecmp(nextHeader, "content-type"); |
- if (comp == 0) { |
- client->rcvContentType = PORT_Strdup(value); |
- } else { |
- comp = PORT_Strcasecmp(nextHeader, "content-length"); |
- if (comp == 0) { |
- contentLength = atoi(value); |
- } |
- } |
- if (thisHeaderEnd != NULL) { |
- nextHeader = thisHeaderEnd + crlfLen; |
- } else { |
- nextHeader = NULL; |
- } |
- } while ((nextHeader != NULL) && (nextHeader < (eoh + crlfLen))); |
- |
- /* Did caller provide a pointer to return content-type? */ |
- if (client->rcv_http_content_type != NULL) { |
- *(client->rcv_http_content_type) = client->rcvContentType; |
- } |
- |
- if (client->rcvContentType == NULL) { |
- client->connectStatus = HTTP_ERROR; |
- goto cleanup; |
- } |
- |
- /* How many bytes remain in current buffer, beyond the header? */ |
- headerLength += eohMarkLen; |
- client->filledupBytes -= headerLength; |
- |
- /* |
- * The headers have passed validation. Now figure out whether the |
- * message is within the caller's size limit (if one was specified). |
- */ |
- switch (contentLength) { |
- case 0: |
- client->rcv_http_data_len = 0; |
- client->connectStatus = HTTP_COMPLETE; |
- *pKeepGoing = PKIX_FALSE; |
- break; |
- |
- case HTTP_UNKNOWN_CONTENT_LENGTH: |
- /* Unknown contentLength indicator.Will be set by |
- * pkix_pl_HttpDefaultClient_RecvBody whey connection get closed */ |
- client->rcv_http_data_len = HTTP_UNKNOWN_CONTENT_LENGTH; |
- contentLength = /* Try to reserve 4K+ buffer */ |
- client->filledupBytes + HTTP_DATA_BUFSIZE; |
- if (client->maxResponseLen > 0 && |
- contentLength > (PKIX_Int32)client->maxResponseLen) { |
- if (client->filledupBytes < client->maxResponseLen) { |
- contentLength = client->maxResponseLen; |
- } else { |
- client->connectStatus = HTTP_ERROR; |
- goto cleanup; |
- } |
- } |
- /* set available number of bytes in the buffer */ |
- client->capacity = contentLength; |
- client->connectStatus = HTTP_RECV_BODY; |
- *pKeepGoing = PKIX_TRUE; |
- break; |
- |
- default: |
- client->rcv_http_data_len = contentLength; |
- if (client->maxResponseLen > 0 && |
- (PKIX_Int32)client->maxResponseLen < contentLength) { |
- client->connectStatus = HTTP_ERROR; |
- goto cleanup; |
- } |
- |
- /* |
- * Do we have all of the message body, or do we need to read some more? |
- */ |
- if ((PKIX_Int32)client->filledupBytes < contentLength) { |
- client->connectStatus = HTTP_RECV_BODY; |
- *pKeepGoing = PKIX_TRUE; |
- } else { |
- client->connectStatus = HTTP_COMPLETE; |
- *pKeepGoing = PKIX_FALSE; |
- } |
- } |
- |
- if (contentLength > 0) { |
- /* allocate a buffer of size contentLength for the content */ |
- PKIX_CHECK(PKIX_PL_Malloc(contentLength, (void **)&body, plContext), |
- PKIX_MALLOCFAILED); |
- |
- /* copy any remaining bytes in current buffer into new buffer */ |
- if (client->filledupBytes > 0) { |
- PORT_Memcpy(body, &(client->rcvBuf[headerLength]), |
- client->filledupBytes); |
- } |
- } |
- |
- PKIX_CHECK(PKIX_PL_Free(client->rcvBuf, plContext), |
- PKIX_FREEFAILED); |
- client->rcvBuf = body; |
- |
-cleanup: |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
-} |
- |
-/* |
- * FUNCTION: PKIX_PL_HttpDefaultClient_Create |
- * DESCRIPTION: |
- * |
- * This function creates a new HttpDefaultClient, and stores the result at |
- * "pClient". |
- * |
- * The HttpClient API does not include a plContext argument in its |
- * function calls. Its value at the time of this Create call must be the |
- * same as when the client is invoked. |
- * |
- * PARAMETERS: |
- * "host" |
- * The name of the server with which we hope to exchange messages. Must |
- * be non-NULL. |
- * "portnum" |
- * The port number to be used for our connection to the server. |
- * "pClient" |
- * The address at which the created HttpDefaultClient is to be stored. |
- * Must be non-NULL. |
- * "plContext" |
- * Platform-specific context pointer. |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a HttpDefaultClient Error if the function fails in |
- * a non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_HttpDefaultClient_Create( |
- const char *host, |
- PRUint16 portnum, |
- PKIX_PL_HttpDefaultClient **pClient, |
- void *plContext) |
-{ |
- PKIX_PL_HttpDefaultClient *client = NULL; |
- |
- PKIX_ENTER(HTTPDEFAULTCLIENT, "PKIX_PL_HttpDefaultClient_Create"); |
- PKIX_NULLCHECK_TWO(pClient, host); |
- |
- /* allocate an HttpDefaultClient */ |
- PKIX_CHECK(PKIX_PL_Object_Alloc |
- (PKIX_HTTPDEFAULTCLIENT_TYPE, |
- sizeof (PKIX_PL_HttpDefaultClient), |
- (PKIX_PL_Object **)&client, |
- plContext), |
- PKIX_COULDNOTCREATEHTTPDEFAULTCLIENTOBJECT); |
- |
- /* Client timeout is overwritten in HttpDefaultClient_RequestCreate |
- * function. Default value will be ignored. */ |
- client->timeout = 0; |
- client->connectStatus = HTTP_NOT_CONNECTED; |
- client->portnum = portnum; |
- client->bytesToWrite = 0; |
- client->send_http_data_len = 0; |
- client->rcv_http_data_len = 0; |
- client->capacity = 0; |
- client->filledupBytes = 0; |
- client->responseCode = 0; |
- client->maxResponseLen = 0; |
- client->GETLen = 0; |
- client->POSTLen = 0; |
- client->pRcv_http_data_len = NULL; |
- client->callbackList = NULL; |
- client->GETBuf = NULL; |
- client->POSTBuf = NULL; |
- client->rcvBuf = NULL; |
- /* "host" is a parsing result by CERT_GetURL function that adds |
- * "end of line" to the value. OK to dup the string. */ |
- client->host = PORT_Strdup(host); |
- if (!client->host) { |
- PKIX_ERROR(PKIX_ALLOCERROR); |
- } |
- client->path = NULL; |
- client->rcvContentType = NULL; |
- client->rcvHeaders = NULL; |
- client->send_http_method = HTTP_POST_METHOD; |
- client->send_http_content_type = NULL; |
- client->send_http_data = NULL; |
- client->rcv_http_response_code = NULL; |
- client->rcv_http_content_type = NULL; |
- client->rcv_http_headers = NULL; |
- client->rcv_http_data = NULL; |
- client->socket = NULL; |
- |
- /* |
- * The HttpClient API does not include a plContext argument in its |
- * function calls. Save it here. |
- */ |
- client->plContext = plContext; |
- |
- *pClient = client; |
- |
-cleanup: |
- if (PKIX_ERROR_RECEIVED) { |
- PKIX_DECREF(client); |
- } |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_HttpDefaultClient_Destroy |
- * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) |
- */ |
-static PKIX_Error * |
-pkix_pl_HttpDefaultClient_Destroy( |
- PKIX_PL_Object *object, |
- void *plContext) |
-{ |
- PKIX_PL_HttpDefaultClient *client = NULL; |
- |
- PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Destroy"); |
- PKIX_NULLCHECK_ONE(object); |
- |
- PKIX_CHECK(pkix_CheckType |
- (object, PKIX_HTTPDEFAULTCLIENT_TYPE, plContext), |
- PKIX_OBJECTNOTANHTTPDEFAULTCLIENT); |
- |
- client = (PKIX_PL_HttpDefaultClient *)object; |
- |
- if (client->rcvHeaders) { |
- PKIX_PL_Free(client->rcvHeaders, plContext); |
- client->rcvHeaders = NULL; |
- } |
- if (client->rcvContentType) { |
- PORT_Free(client->rcvContentType); |
- client->rcvContentType = NULL; |
- } |
- if (client->GETBuf != NULL) { |
- PR_smprintf_free(client->GETBuf); |
- client->GETBuf = NULL; |
- } |
- if (client->POSTBuf != NULL) { |
- PKIX_PL_Free(client->POSTBuf, plContext); |
- client->POSTBuf = NULL; |
- } |
- if (client->rcvBuf != NULL) { |
- PKIX_PL_Free(client->rcvBuf, plContext); |
- client->rcvBuf = NULL; |
- } |
- if (client->host) { |
- PORT_Free(client->host); |
- client->host = NULL; |
- } |
- if (client->path) { |
- PORT_Free(client->path); |
- client->path = NULL; |
- } |
- PKIX_DECREF(client->socket); |
- |
-cleanup: |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_HttpDefaultClient_RegisterSelf |
- * |
- * DESCRIPTION: |
- * Registers PKIX_PL_HTTPDEFAULTCLIENT_TYPE and its related |
- * functions with systemClasses[] |
- * |
- * THREAD SAFETY: |
- * Not Thread Safe - for performance and complexity reasons |
- * |
- * Since this function is only called by PKIX_PL_Initialize, which should |
- * only be called once, it is acceptable that this function is not |
- * thread-safe. |
- */ |
-PKIX_Error * |
-pkix_pl_HttpDefaultClient_RegisterSelf(void *plContext) |
-{ |
- extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; |
- pkix_ClassTable_Entry *entry = |
- &systemClasses[PKIX_HTTPDEFAULTCLIENT_TYPE]; |
- |
- PKIX_ENTER(HTTPDEFAULTCLIENT, |
- "pkix_pl_HttpDefaultClient_RegisterSelf"); |
- |
- entry->description = "HttpDefaultClient"; |
- entry->typeObjectSize = sizeof(PKIX_PL_HttpDefaultClient); |
- entry->destructor = pkix_pl_HttpDefaultClient_Destroy; |
- |
- httpClient.version = 1; |
- httpClient.fcnTable.ftable1 = vtable; |
- (void)SEC_RegisterDefaultHttpClient(&httpClient); |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
-} |
- |
-/* --Private-HttpDefaultClient-I/O-Functions---------------------------- */ |
-/* |
- * FUNCTION: pkix_pl_HttpDefaultClient_ConnectContinue |
- * DESCRIPTION: |
- * |
- * This function determines whether a socket Connect initiated earlier for the |
- * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a flag |
- * indicating whether processing can continue without further input. |
- * |
- * PARAMETERS: |
- * "client" |
- * The address of the HttpDefaultClient object. Must be non-NULL. |
- * "pKeepGoing" |
- * The address at which the Boolean state machine flag is stored to |
- * indicate whether processing can continue without further input. |
- * Must be non-NULL. |
- * "plContext" |
- * Platform-specific context pointer. |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a HttpDefaultClient Error if the function fails in a |
- * non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_HttpDefaultClient_ConnectContinue( |
- PKIX_PL_HttpDefaultClient *client, |
- PKIX_Boolean *pKeepGoing, |
- void *plContext) |
-{ |
- PRErrorCode status; |
- PKIX_Boolean keepGoing = PKIX_FALSE; |
- PKIX_PL_Socket_Callback *callbackList = NULL; |
- |
- PKIX_ENTER |
- (HTTPDEFAULTCLIENT, |
- "pkix_pl_HttpDefaultClient_ConnectContinue"); |
- PKIX_NULLCHECK_ONE(client); |
- |
- callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; |
- |
- PKIX_CHECK(callbackList->connectcontinueCallback |
- (client->socket, &status, plContext), |
- PKIX_SOCKETCONNECTCONTINUEFAILED); |
- |
- if (status == 0) { |
- client->connectStatus = HTTP_CONNECTED; |
- keepGoing = PKIX_TRUE; |
- } else if (status != PR_IN_PROGRESS_ERROR) { |
- PKIX_ERROR(PKIX_UNEXPECTEDERRORINESTABLISHINGCONNECTION); |
- } |
- |
- *pKeepGoing = keepGoing; |
- |
-cleanup: |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_HttpDefaultClient_Send |
- * DESCRIPTION: |
- * |
- * This function creates and sends HTTP-protocol headers and, if applicable, |
- * data, for the HttpDefaultClient "client", and stores in "pKeepGoing" a flag |
- * indicating whether processing can continue without further input, and at |
- * "pBytesTransferred" the number of bytes sent. |
- * |
- * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use |
- * and that transmission has not completed. |
- * |
- * PARAMETERS: |
- * "client" |
- * The address of the HttpDefaultClient object. Must be non-NULL. |
- * "pKeepGoing" |
- * The address at which the Boolean state machine flag is stored to |
- * indicate whether processing can continue without further input. |
- * Must be non-NULL. |
- * "pBytesTransferred" |
- * The address at which the number of bytes sent is stored. Must be |
- * non-NULL. |
- * "plContext" |
- * Platform-specific context pointer. |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a HttpDefaultClient Error if the function fails in a |
- * non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_HttpDefaultClient_Send( |
- PKIX_PL_HttpDefaultClient *client, |
- PKIX_Boolean *pKeepGoing, |
- PKIX_UInt32 *pBytesTransferred, |
- void *plContext) |
-{ |
- PKIX_Int32 bytesWritten = 0; |
- PKIX_Int32 lenToWrite = 0; |
- PKIX_PL_Socket_Callback *callbackList = NULL; |
- char *dataToWrite = NULL; |
- |
- PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Send"); |
- PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred); |
- |
- *pKeepGoing = PKIX_FALSE; |
- |
- /* Do we have anything waiting to go? */ |
- if ((client->GETBuf) || (client->POSTBuf)) { |
- |
- if (client->GETBuf) { |
- dataToWrite = client->GETBuf; |
- lenToWrite = client->GETLen; |
- } else { |
- dataToWrite = client->POSTBuf; |
- lenToWrite = client->POSTLen; |
- } |
- |
- callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; |
- |
- PKIX_CHECK(callbackList->sendCallback |
- (client->socket, |
- dataToWrite, |
- lenToWrite, |
- &bytesWritten, |
- plContext), |
- PKIX_SOCKETSENDFAILED); |
- |
- client->rcvBuf = NULL; |
- client->capacity = 0; |
- client->filledupBytes = 0; |
- |
- /* |
- * If the send completed we can proceed to try for the |
- * response. If the send did not complete we will have |
- * to poll for completion later. |
- */ |
- if (bytesWritten >= 0) { |
- client->connectStatus = HTTP_RECV_HDR; |
- *pKeepGoing = PKIX_TRUE; |
- } else { |
- client->connectStatus = HTTP_SEND_PENDING; |
- *pKeepGoing = PKIX_FALSE; |
- } |
- |
- } |
- |
- *pBytesTransferred = bytesWritten; |
- |
-cleanup: |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_HttpDefaultClient_SendContinue |
- * DESCRIPTION: |
- * |
- * This function determines whether the sending of the HTTP message for the |
- * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a |
- * flag indicating whether processing can continue without further input, and |
- * at "pBytesTransferred" the number of bytes sent. |
- * |
- * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use |
- * and that transmission has not completed. |
- * |
- * PARAMETERS: |
- * "client" |
- * The address of the HttpDefaultClient object. Must be non-NULL. |
- * "pKeepGoing" |
- * The address at which the Boolean state machine flag is stored to |
- * indicate whether processing can continue without further input. |
- * Must be non-NULL. |
- * "pBytesTransferred" |
- * The address at which the number of bytes sent is stored. Must be |
- * non-NULL. |
- * "plContext" |
- * Platform-specific context pointer. |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a HttpDefaultClient Error if the function fails in a |
- * non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_HttpDefaultClient_SendContinue( |
- PKIX_PL_HttpDefaultClient *client, |
- PKIX_Boolean *pKeepGoing, |
- PKIX_UInt32 *pBytesTransferred, |
- void *plContext) |
-{ |
- PKIX_Int32 bytesWritten = 0; |
- PKIX_PL_Socket_Callback *callbackList = NULL; |
- |
- PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_SendContinue"); |
- PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred); |
- |
- *pKeepGoing = PKIX_FALSE; |
- |
- callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; |
- |
- PKIX_CHECK(callbackList->pollCallback |
- (client->socket, &bytesWritten, NULL, plContext), |
- PKIX_SOCKETPOLLFAILED); |
- |
- /* |
- * If the send completed we can proceed to try for the |
- * response. If the send did not complete we will have |
- * continue to poll. |
- */ |
- if (bytesWritten >= 0) { |
- client->connectStatus = HTTP_RECV_HDR; |
- *pKeepGoing = PKIX_TRUE; |
- } |
- |
- *pBytesTransferred = bytesWritten; |
- |
-cleanup: |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_HttpDefaultClient_RecvHdr |
- * DESCRIPTION: |
- * |
- * This function receives HTTP headers for the HttpDefaultClient "client", and |
- * stores in "pKeepGoing" a flag indicating whether processing can continue |
- * without further input. |
- * |
- * PARAMETERS: |
- * "client" |
- * The address of the HttpDefaultClient object. Must be non-NULL. |
- * "pKeepGoing" |
- * The address at which the Boolean state machine flag is stored to |
- * indicate whether processing can continue without further input. |
- * Must be non-NULL. |
- * "plContext" |
- * Platform-specific context pointer. |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a HttpDefaultClient Error if the function fails in a |
- * non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_HttpDefaultClient_RecvHdr( |
- PKIX_PL_HttpDefaultClient *client, |
- PKIX_Boolean *pKeepGoing, |
- void *plContext) |
-{ |
- PKIX_UInt32 bytesToRead = 0; |
- PKIX_Int32 bytesRead = 0; |
- PKIX_PL_Socket_Callback *callbackList = NULL; |
- |
- PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RecvHdr"); |
- PKIX_NULLCHECK_TWO(client, pKeepGoing); |
- |
- /* |
- * rcvbuf, capacity, and filledupBytes were |
- * initialized when we wrote the headers. We begin by reading |
- * HTTP_HEADER_BUFSIZE bytes, repeatedly increasing the buffersize and |
- * reading again if necessary, until we have read the end-of-header |
- * marker, "\r\n\r\n", or have reached our maximum. |
- */ |
- client->capacity += HTTP_HEADER_BUFSIZE; |
- PKIX_CHECK(PKIX_PL_Realloc |
- (client->rcvBuf, |
- client->capacity, |
- (void **)&(client->rcvBuf), |
- plContext), |
- PKIX_REALLOCFAILED); |
- |
- bytesToRead = client->capacity - client->filledupBytes; |
- |
- callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; |
- |
- PKIX_CHECK(callbackList->recvCallback |
- (client->socket, |
- (void *)&(client->rcvBuf[client->filledupBytes]), |
- bytesToRead, |
- &bytesRead, |
- plContext), |
- PKIX_SOCKETRECVFAILED); |
- |
- if (bytesRead > 0) { |
- /* client->filledupBytes will be adjusted by |
- * pkix_pl_HttpDefaultClient_HdrCheckComplete */ |
- PKIX_CHECK( |
- pkix_pl_HttpDefaultClient_HdrCheckComplete(client, bytesRead, |
- pKeepGoing, |
- plContext), |
- PKIX_HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED); |
- } else { |
- client->connectStatus = HTTP_RECV_HDR_PENDING; |
- *pKeepGoing = PKIX_FALSE; |
- } |
- |
-cleanup: |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_HttpDefaultClient_RecvHdrContinue |
- * DESCRIPTION: |
- * |
- * This function determines whether the receiving of the HTTP headers for the |
- * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a flag |
- * indicating whether processing can continue without further input. |
- * |
- * PARAMETERS: |
- * "client" |
- * The address of the HttpDefaultClient object. Must be non-NULL. |
- * "pKeepGoing" |
- * The address at which the Boolean state machine flag is stored to |
- * indicate whether processing can continue without further input. |
- * Must be non-NULL. |
- * "plContext" |
- * Platform-specific context pointer. |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a HttpDefaultClient Error if the function fails in a |
- * non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_HttpDefaultClient_RecvHdrContinue( |
- PKIX_PL_HttpDefaultClient *client, |
- PKIX_Boolean *pKeepGoing, |
- void *plContext) |
-{ |
- PKIX_Int32 bytesRead = 0; |
- PKIX_PL_Socket_Callback *callbackList = NULL; |
- |
- PKIX_ENTER |
- (HTTPDEFAULTCLIENT, |
- "pkix_pl_HttpDefaultClient_RecvHdrContinue"); |
- PKIX_NULLCHECK_TWO(client, pKeepGoing); |
- |
- callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; |
- |
- PKIX_CHECK(callbackList->pollCallback |
- (client->socket, NULL, &bytesRead, plContext), |
- PKIX_SOCKETPOLLFAILED); |
- |
- if (bytesRead > 0) { |
- client->filledupBytes += bytesRead; |
- |
- PKIX_CHECK(pkix_pl_HttpDefaultClient_HdrCheckComplete |
- (client, bytesRead, pKeepGoing, plContext), |
- PKIX_HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED); |
- |
- } else { |
- |
- *pKeepGoing = PKIX_FALSE; |
- |
- } |
- |
-cleanup: |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_HttpDefaultClient_RecvBody |
- * DESCRIPTION: |
- * |
- * This function processes the contents of the first buffer of a received |
- * HTTP-protocol message for the HttpDefaultClient "client", and stores in |
- * "pKeepGoing" a flag indicating whether processing can continue without |
- * further input. |
- * |
- * PARAMETERS: |
- * "client" |
- * The address of the HttpDefaultClient object. Must be non-NULL. |
- * "pKeepGoing" |
- * The address at which the Boolean state machine flag is stored to |
- * indicate whether processing can continue without further input. |
- * Must be non-NULL. |
- * "plContext" |
- * Platform-specific context pointer. |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a HttpDefaultClient Error if the function fails in a |
- * non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_HttpDefaultClient_RecvBody( |
- PKIX_PL_HttpDefaultClient *client, |
- PKIX_Boolean *pKeepGoing, |
- void *plContext) |
-{ |
- PKIX_Int32 bytesRead = 0; |
- PKIX_Int32 bytesToRead = 0; |
- PKIX_PL_Socket_Callback *callbackList = NULL; |
- |
- PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RecvBody"); |
- PKIX_NULLCHECK_TWO(client, pKeepGoing); |
- |
- callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; |
- |
- if (client->rcv_http_data_len != HTTP_UNKNOWN_CONTENT_LENGTH) { |
- bytesToRead = client->rcv_http_data_len - |
- client->filledupBytes; |
- } else { |
- /* Reading till the EOF. Context length is not known.*/ |
- /* Check the buffer capacity: increase and |
- * reallocate if it is low. */ |
- int freeBuffSize = client->capacity - client->filledupBytes; |
- if (freeBuffSize < HTTP_MIN_AVAILABLE_BUFFER_SIZE) { |
- /* New length will be consist of available(downloaded) bytes, |
- * plus remaining capacity, plus new expansion. */ |
- int currBuffSize = client->capacity; |
- /* Try to increase the buffer by 4K */ |
- unsigned int newLength = currBuffSize + HTTP_DATA_BUFSIZE; |
- if (client->maxResponseLen > 0 && |
- newLength > client->maxResponseLen) { |
- newLength = client->maxResponseLen; |
- } |
- /* Check if we can grow the buffer and report an error if |
- * new size is not larger than the current size of the buffer.*/ |
- if (newLength <= client->filledupBytes) { |
- client->rcv_http_data_len = client->filledupBytes; |
- client->connectStatus = HTTP_ERROR; |
- *pKeepGoing = PKIX_FALSE; |
- goto cleanup; |
- } |
- if (client->capacity < newLength) { |
- client->capacity = newLength; |
- PKIX_CHECK( |
- PKIX_PL_Realloc(client->rcvBuf, newLength, |
- (void**)&client->rcvBuf, plContext), |
- PKIX_REALLOCFAILED); |
- freeBuffSize = client->capacity - |
- client->filledupBytes; |
- } |
- } |
- bytesToRead = freeBuffSize; |
- } |
- |
- /* Use poll callback if waiting on non-blocking IO */ |
- if (client->connectStatus == HTTP_RECV_BODY_PENDING) { |
- PKIX_CHECK(callbackList->pollCallback |
- (client->socket, NULL, &bytesRead, plContext), |
- PKIX_SOCKETPOLLFAILED); |
- } else { |
- PKIX_CHECK(callbackList->recvCallback |
- (client->socket, |
- (void *)&(client->rcvBuf[client->filledupBytes]), |
- bytesToRead, |
- &bytesRead, |
- plContext), |
- PKIX_SOCKETRECVFAILED); |
- } |
- |
- /* If bytesRead < 0, an error will be thrown by recvCallback, so |
- * need to handle >= 0 cases. */ |
- |
- /* bytesRead == 0 - IO was blocked. */ |
- if (bytesRead == 0) { |
- client->connectStatus = HTTP_RECV_BODY_PENDING; |
- *pKeepGoing = PKIX_TRUE; |
- goto cleanup; |
- } |
- |
- /* We got something. Did we get it all? */ |
- client->filledupBytes += bytesRead; |
- |
- /* continue if not enough bytes read or if complete size of |
- * transfer is unknown */ |
- if (bytesToRead > bytesRead || |
- client->rcv_http_data_len == HTTP_UNKNOWN_CONTENT_LENGTH) { |
- *pKeepGoing = PKIX_TRUE; |
- goto cleanup; |
- } |
- client->connectStatus = HTTP_COMPLETE; |
- *pKeepGoing = PKIX_FALSE; |
- |
-cleanup: |
- if (pkixErrorResult && pkixErrorResult->errCode == |
- PKIX_PRRECVREPORTSNETWORKCONNECTIONCLOSED) { |
- if (client->rcv_http_data_len == HTTP_UNKNOWN_CONTENT_LENGTH) { |
- client->rcv_http_data_len = client->filledupBytes; |
- client->connectStatus = HTTP_COMPLETE; |
- *pKeepGoing = PKIX_FALSE; |
- PKIX_DECREF(pkixErrorResult); |
- } else { |
- client->connectStatus = HTTP_ERROR; |
- } |
- } |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_HttpDefaultClient_Dispatch |
- * DESCRIPTION: |
- * |
- * This function is the state machine dispatcher for the HttpDefaultClient |
- * pointed to by "client". Results are returned by changes to various fields |
- * in the context. |
- * |
- * PARAMETERS: |
- * "client" |
- * The address of the HttpDefaultClient object. Must be non-NULL. |
- * "plContext" |
- * Platform-specific context pointer. |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a HttpDefaultClient Error if the function fails in a |
- * non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_HttpDefaultClient_Dispatch( |
- PKIX_PL_HttpDefaultClient *client, |
- void *plContext) |
-{ |
- PKIX_UInt32 bytesTransferred = 0; |
- PKIX_Boolean keepGoing = PKIX_TRUE; |
- |
- PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Dispatch"); |
- PKIX_NULLCHECK_ONE(client); |
- |
- while (keepGoing) { |
- switch (client->connectStatus) { |
- case HTTP_CONNECT_PENDING: |
- PKIX_CHECK(pkix_pl_HttpDefaultClient_ConnectContinue |
- (client, &keepGoing, plContext), |
- PKIX_HTTPDEFAULTCLIENTCONNECTCONTINUEFAILED); |
- break; |
- case HTTP_CONNECTED: |
- PKIX_CHECK(pkix_pl_HttpDefaultClient_Send |
- (client, &keepGoing, &bytesTransferred, plContext), |
- PKIX_HTTPDEFAULTCLIENTSENDFAILED); |
- break; |
- case HTTP_SEND_PENDING: |
- PKIX_CHECK(pkix_pl_HttpDefaultClient_SendContinue |
- (client, &keepGoing, &bytesTransferred, plContext), |
- PKIX_HTTPDEFAULTCLIENTSENDCONTINUEFAILED); |
- break; |
- case HTTP_RECV_HDR: |
- PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvHdr |
- (client, &keepGoing, plContext), |
- PKIX_HTTPDEFAULTCLIENTRECVHDRFAILED); |
- break; |
- case HTTP_RECV_HDR_PENDING: |
- PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvHdrContinue |
- (client, &keepGoing, plContext), |
- PKIX_HTTPDEFAULTCLIENTRECVHDRCONTINUEFAILED); |
- break; |
- case HTTP_RECV_BODY: |
- case HTTP_RECV_BODY_PENDING: |
- PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvBody |
- (client, &keepGoing, plContext), |
- PKIX_HTTPDEFAULTCLIENTRECVBODYFAILED); |
- break; |
- case HTTP_ERROR: |
- case HTTP_COMPLETE: |
- keepGoing = PKIX_FALSE; |
- break; |
- case HTTP_NOT_CONNECTED: |
- default: |
- PKIX_ERROR(PKIX_HTTPDEFAULTCLIENTINILLEGALSTATE); |
- } |
- } |
- |
-cleanup: |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
-} |
- |
-/* |
- * --HttpClient vtable functions |
- * See comments in ocspt.h for the function (wrappers) that return SECStatus. |
- * The functions that return PKIX_Error* are the libpkix implementations. |
- */ |
- |
-PKIX_Error * |
-pkix_pl_HttpDefaultClient_CreateSession( |
- const char *host, |
- PRUint16 portnum, |
- SEC_HTTP_SERVER_SESSION *pSession, |
- void *plContext) |
-{ |
- PKIX_PL_HttpDefaultClient *client = NULL; |
- |
- PKIX_ENTER |
- (HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_CreateSession"); |
- PKIX_NULLCHECK_TWO(host, pSession); |
- |
- PKIX_CHECK(pkix_pl_HttpDefaultClient_Create |
- (host, portnum, &client, plContext), |
- PKIX_HTTPDEFAULTCLIENTCREATEFAILED); |
- |
- *pSession = (SEC_HTTP_SERVER_SESSION)client; |
- |
-cleanup: |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
- |
-} |
- |
-PKIX_Error * |
-pkix_pl_HttpDefaultClient_KeepAliveSession( |
- SEC_HTTP_SERVER_SESSION session, |
- PRPollDesc **pPollDesc, |
- void *plContext) |
-{ |
- PKIX_ENTER |
- (HTTPDEFAULTCLIENT, |
- "pkix_pl_HttpDefaultClient_KeepAliveSession"); |
- PKIX_NULLCHECK_TWO(session, pPollDesc); |
- |
- PKIX_CHECK(pkix_CheckType |
- ((PKIX_PL_Object *)session, |
- PKIX_HTTPDEFAULTCLIENT_TYPE, |
- plContext), |
- PKIX_SESSIONNOTANHTTPDEFAULTCLIENT); |
- |
- /* XXX Not implemented */ |
- |
-cleanup: |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
- |
-} |
- |
-PKIX_Error * |
-pkix_pl_HttpDefaultClient_RequestCreate( |
- SEC_HTTP_SERVER_SESSION session, |
- const char *http_protocol_variant, /* usually "http" */ |
- const char *path_and_query_string, |
- const char *http_request_method, |
- const PRIntervalTime timeout, |
- SEC_HTTP_REQUEST_SESSION *pRequest, |
- void *plContext) |
-{ |
- PKIX_PL_HttpDefaultClient *client = NULL; |
- PKIX_PL_Socket *socket = NULL; |
- PKIX_PL_Socket_Callback *callbackList = NULL; |
- PRFileDesc *fileDesc = NULL; |
- PRErrorCode status = 0; |
- |
- PKIX_ENTER |
- (HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RequestCreate"); |
- PKIX_NULLCHECK_TWO(session, pRequest); |
- |
- PKIX_CHECK(pkix_CheckType |
- ((PKIX_PL_Object *)session, |
- PKIX_HTTPDEFAULTCLIENT_TYPE, |
- plContext), |
- PKIX_SESSIONNOTANHTTPDEFAULTCLIENT); |
- |
- client = (PKIX_PL_HttpDefaultClient *)session; |
- |
- /* We only know how to do http */ |
- if (PORT_Strncasecmp(http_protocol_variant, "http", 4) != 0) { |
- PKIX_ERROR(PKIX_UNRECOGNIZEDPROTOCOLREQUESTED); |
- } |
- |
- if (PORT_Strncasecmp(http_request_method, "POST", 4) == 0) { |
- client->send_http_method = HTTP_POST_METHOD; |
- } else if (PORT_Strncasecmp(http_request_method, "GET", 3) == 0) { |
- client->send_http_method = HTTP_GET_METHOD; |
- } else { |
- /* We only know how to do POST and GET */ |
- PKIX_ERROR(PKIX_UNRECOGNIZEDREQUESTMETHOD); |
- } |
- |
- if (path_and_query_string) { |
- /* "path_and_query_string" is a parsing result by CERT_GetURL |
- * function that adds "end of line" to the value. OK to dup |
- * the string. */ |
- client->path = PORT_Strdup(path_and_query_string); |
- if (!client->path) { |
- PKIX_ERROR(PKIX_ALLOCERROR); |
- } |
- } |
- |
- client->timeout = timeout; |
- |
-#if 0 |
- PKIX_CHECK(pkix_HttpCertStore_FindSocketConnection |
- (timeout, |
- "variation.red.iplanet.com", /* (char *)client->host, */ |
- 2001, /* client->portnum, */ |
- &status, |
- &socket, |
- plContext), |
- PKIX_HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED); |
-#else |
- PKIX_CHECK(pkix_HttpCertStore_FindSocketConnection |
- (timeout, |
- (char *)client->host, |
- client->portnum, |
- &status, |
- &socket, |
- plContext), |
- PKIX_HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED); |
-#endif |
- |
- client->socket = socket; |
- |
- PKIX_CHECK(pkix_pl_Socket_GetCallbackList |
- (socket, &callbackList, plContext), |
- PKIX_SOCKETGETCALLBACKLISTFAILED); |
- |
- client->callbackList = (void *)callbackList; |
- |
- PKIX_CHECK(pkix_pl_Socket_GetPRFileDesc |
- (socket, &fileDesc, plContext), |
- PKIX_SOCKETGETPRFILEDESCFAILED); |
- |
- client->pollDesc.fd = fileDesc; |
- client->pollDesc.in_flags = 0; |
- client->pollDesc.out_flags = 0; |
- |
- client->send_http_data = NULL; |
- client->send_http_data_len = 0; |
- client->send_http_content_type = NULL; |
- |
- client->connectStatus = |
- ((status == 0) ? HTTP_CONNECTED : HTTP_CONNECT_PENDING); |
- |
- /* Request object is the same object as Session object */ |
- PKIX_INCREF(client); |
- *pRequest = client; |
- |
-cleanup: |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
- |
-} |
- |
-PKIX_Error * |
-pkix_pl_HttpDefaultClient_SetPostData( |
- SEC_HTTP_REQUEST_SESSION request, |
- const char *http_data, |
- const PRUint32 http_data_len, |
- const char *http_content_type, |
- void *plContext) |
-{ |
- PKIX_PL_HttpDefaultClient *client = NULL; |
- |
- PKIX_ENTER |
- (HTTPDEFAULTCLIENT, |
- "pkix_pl_HttpDefaultClient_SetPostData"); |
- PKIX_NULLCHECK_ONE(request); |
- |
- PKIX_CHECK(pkix_CheckType |
- ((PKIX_PL_Object *)request, |
- PKIX_HTTPDEFAULTCLIENT_TYPE, |
- plContext), |
- PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); |
- |
- client = (PKIX_PL_HttpDefaultClient *)request; |
- |
- client->send_http_data = http_data; |
- client->send_http_data_len = http_data_len; |
- client->send_http_content_type = http_content_type; |
- |
- /* Caller is allowed to give NULL or empty string for content_type */ |
- if ((client->send_http_content_type == NULL) || |
- (*(client->send_http_content_type) == '\0')) { |
- client->send_http_content_type = "application/ocsp-request"; |
- } |
- |
-cleanup: |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
- |
-} |
- |
-PKIX_Error * |
-pkix_pl_HttpDefaultClient_TrySendAndReceive( |
- SEC_HTTP_REQUEST_SESSION request, |
- PRUint16 *http_response_code, |
- const char **http_response_content_type, |
- const char **http_response_headers, |
- const char **http_response_data, |
- PRUint32 *http_response_data_len, |
- PRPollDesc **pPollDesc, |
- SECStatus *pSECReturn, |
- void *plContext) |
-{ |
- PKIX_PL_HttpDefaultClient *client = NULL; |
- PKIX_UInt32 postLen = 0; |
- PRPollDesc *pollDesc = NULL; |
- char *sendbuf = NULL; |
- char portstr[16]; |
- |
- PKIX_ENTER |
- (HTTPDEFAULTCLIENT, |
- "pkix_pl_HttpDefaultClient_TrySendAndReceive"); |
- |
- PKIX_NULLCHECK_ONE(request); |
- |
- PKIX_CHECK(pkix_CheckType |
- ((PKIX_PL_Object *)request, |
- PKIX_HTTPDEFAULTCLIENT_TYPE, |
- plContext), |
- PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); |
- |
- client = (PKIX_PL_HttpDefaultClient *)request; |
- |
- if (!pPollDesc && client->timeout == 0) { |
- PKIX_ERROR_FATAL(PKIX_NULLARGUMENT); |
- } |
- |
- if (pPollDesc) { |
- pollDesc = *pPollDesc; |
- } |
- |
- /* if not continuing from an earlier WOULDBLOCK return... */ |
- if (pollDesc == NULL) { |
- |
- if (!((client->connectStatus == HTTP_CONNECTED) || |
- (client->connectStatus == HTTP_CONNECT_PENDING))) { |
- PKIX_ERROR(PKIX_HTTPCLIENTININVALIDSTATE); |
- } |
- |
- /* Did caller provide a value for response length? */ |
- if (http_response_data_len != NULL) { |
- client->pRcv_http_data_len = http_response_data_len; |
- client->maxResponseLen = *http_response_data_len; |
- } |
- |
- client->rcv_http_response_code = http_response_code; |
- client->rcv_http_content_type = http_response_content_type; |
- client->rcv_http_headers = http_response_headers; |
- client->rcv_http_data = http_response_data; |
- |
- /* prepare the message */ |
- portstr[0] = '\0'; |
- if (client->portnum != 80) { |
- PR_snprintf(portstr, sizeof(portstr), ":%d", |
- client->portnum); |
- } |
- |
- if (client->send_http_method == HTTP_POST_METHOD) { |
- sendbuf = PR_smprintf |
- ("POST %s HTTP/1.0\r\nHost: %s%s\r\n" |
- "Content-Type: %s\r\nContent-Length: %u\r\n\r\n", |
- client->path, |
- client->host, |
- portstr, |
- client->send_http_content_type, |
- client->send_http_data_len); |
- postLen = PORT_Strlen(sendbuf); |
- |
- client->POSTLen = postLen + client->send_http_data_len; |
- |
- /* allocate postBuffer big enough for header + data */ |
- PKIX_CHECK(PKIX_PL_Malloc |
- (client->POSTLen, |
- (void **)&(client->POSTBuf), |
- plContext), |
- PKIX_MALLOCFAILED); |
- |
- /* copy header into postBuffer */ |
- PORT_Memcpy(client->POSTBuf, sendbuf, postLen); |
- |
- /* append data after header */ |
- PORT_Memcpy(&client->POSTBuf[postLen], |
- client->send_http_data, |
- client->send_http_data_len); |
- |
- /* PR_smprintf_free original header buffer */ |
- PR_smprintf_free(sendbuf); |
- sendbuf = NULL; |
- |
- } else if (client->send_http_method == HTTP_GET_METHOD) { |
- client->GETBuf = PR_smprintf |
- ("GET %s HTTP/1.0\r\nHost: %s%s\r\n\r\n", |
- client->path, |
- client->host, |
- portstr); |
- client->GETLen = PORT_Strlen(client->GETBuf); |
- } |
- |
- } |
- |
- /* continue according to state */ |
- PKIX_CHECK(pkix_pl_HttpDefaultClient_Dispatch(client, plContext), |
- PKIX_HTTPDEFAULTCLIENTDISPATCHFAILED); |
- |
- switch (client->connectStatus) { |
- case HTTP_CONNECT_PENDING: |
- case HTTP_SEND_PENDING: |
- case HTTP_RECV_HDR_PENDING: |
- case HTTP_RECV_BODY_PENDING: |
- pollDesc = &(client->pollDesc); |
- *pSECReturn = SECWouldBlock; |
- break; |
- case HTTP_ERROR: |
- /* Did caller provide a pointer for length? */ |
- if (client->pRcv_http_data_len != NULL) { |
- /* Was error "response too big?" */ |
- if (client->rcv_http_data_len != |
- HTTP_UNKNOWN_CONTENT_LENGTH && |
- client->maxResponseLen >= |
- client->rcv_http_data_len) { |
- /* Yes, report needed space */ |
- *(client->pRcv_http_data_len) = |
- client->rcv_http_data_len; |
- } else { |
- /* No, report problem other than size */ |
- *(client->pRcv_http_data_len) = 0; |
- } |
- } |
- |
- pollDesc = NULL; |
- *pSECReturn = SECFailure; |
- break; |
- case HTTP_COMPLETE: |
- *(client->rcv_http_response_code) = |
- client->responseCode; |
- if (client->pRcv_http_data_len != NULL) { |
- *http_response_data_len = |
- client->rcv_http_data_len; |
- } |
- if (client->rcv_http_data != NULL) { |
- *(client->rcv_http_data) = client->rcvBuf; |
- } |
- pollDesc = NULL; |
- *pSECReturn = SECSuccess; |
- break; |
- case HTTP_NOT_CONNECTED: |
- case HTTP_CONNECTED: |
- case HTTP_RECV_HDR: |
- case HTTP_RECV_BODY: |
- default: |
- pollDesc = NULL; |
- *pSECReturn = SECFailure; |
- PKIX_ERROR(PKIX_HTTPCLIENTININVALIDSTATE); |
- break; |
- } |
- |
- if (pPollDesc) { |
- *pPollDesc = pollDesc; |
- } |
- |
-cleanup: |
- if (sendbuf) { |
- PR_smprintf_free(sendbuf); |
- } |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
- |
-} |
- |
-PKIX_Error * |
-pkix_pl_HttpDefaultClient_Cancel( |
- SEC_HTTP_REQUEST_SESSION request, |
- void *plContext) |
-{ |
- PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Cancel"); |
- PKIX_NULLCHECK_ONE(request); |
- |
- PKIX_CHECK(pkix_CheckType |
- ((PKIX_PL_Object *)request, |
- PKIX_HTTPDEFAULTCLIENT_TYPE, |
- plContext), |
- PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); |
- |
- /* XXX Not implemented */ |
- |
-cleanup: |
- |
- PKIX_RETURN(HTTPDEFAULTCLIENT); |
- |
-} |
- |
-SECStatus |
-pkix_pl_HttpDefaultClient_CreateSessionFcn( |
- const char *host, |
- PRUint16 portnum, |
- SEC_HTTP_SERVER_SESSION *pSession) |
-{ |
- PKIX_Error *err = pkix_pl_HttpDefaultClient_CreateSession |
- (host, portnum, pSession, plContext); |
- |
- if (err) { |
- PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); |
- return SECFailure; |
- } |
- return SECSuccess; |
-} |
- |
-SECStatus |
-pkix_pl_HttpDefaultClient_KeepAliveSessionFcn( |
- SEC_HTTP_SERVER_SESSION session, |
- PRPollDesc **pPollDesc) |
-{ |
- PKIX_Error *err = pkix_pl_HttpDefaultClient_KeepAliveSession |
- (session, pPollDesc, plContext); |
- |
- if (err) { |
- PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); |
- return SECFailure; |
- } |
- return SECSuccess; |
-} |
- |
-SECStatus |
-pkix_pl_HttpDefaultClient_FreeSessionFcn( |
- SEC_HTTP_SERVER_SESSION session) |
-{ |
- PKIX_Error *err = |
- PKIX_PL_Object_DecRef((PKIX_PL_Object *)(session), plContext); |
- |
- if (err) { |
- PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); |
- return SECFailure; |
- } |
- return SECSuccess; |
-} |
- |
-SECStatus |
-pkix_pl_HttpDefaultClient_RequestCreateFcn( |
- SEC_HTTP_SERVER_SESSION session, |
- const char *http_protocol_variant, /* usually "http" */ |
- const char *path_and_query_string, |
- const char *http_request_method, |
- const PRIntervalTime timeout, |
- SEC_HTTP_REQUEST_SESSION *pRequest) |
-{ |
- PKIX_Error *err = pkix_pl_HttpDefaultClient_RequestCreate |
- (session, |
- http_protocol_variant, |
- path_and_query_string, |
- http_request_method, |
- timeout, |
- pRequest, |
- plContext); |
- |
- if (err) { |
- PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); |
- return SECFailure; |
- } |
- return SECSuccess; |
-} |
- |
-SECStatus |
-pkix_pl_HttpDefaultClient_SetPostDataFcn( |
- SEC_HTTP_REQUEST_SESSION request, |
- const char *http_data, |
- const PRUint32 http_data_len, |
- const char *http_content_type) |
-{ |
- PKIX_Error *err = |
- pkix_pl_HttpDefaultClient_SetPostData(request, http_data, |
- http_data_len, |
- http_content_type, |
- plContext); |
- if (err) { |
- PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); |
- return SECFailure; |
- } |
- return SECSuccess; |
-} |
- |
-SECStatus |
-pkix_pl_HttpDefaultClient_AddHeaderFcn( |
- SEC_HTTP_REQUEST_SESSION request, |
- const char *http_header_name, |
- const char *http_header_value) |
-{ |
- /* Not supported */ |
- return SECFailure; |
-} |
- |
-SECStatus |
-pkix_pl_HttpDefaultClient_TrySendAndReceiveFcn( |
- SEC_HTTP_REQUEST_SESSION request, |
- PRPollDesc **pPollDesc, |
- PRUint16 *http_response_code, |
- const char **http_response_content_type, |
- const char **http_response_headers, |
- const char **http_response_data, |
- PRUint32 *http_response_data_len) |
-{ |
- SECStatus rv = SECFailure; |
- |
- PKIX_Error *err = pkix_pl_HttpDefaultClient_TrySendAndReceive |
- (request, |
- http_response_code, |
- http_response_content_type, |
- http_response_headers, |
- http_response_data, |
- http_response_data_len, |
- pPollDesc, |
- &rv, |
- plContext); |
- |
- if (err) { |
- PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); |
- return rv; |
- } |
- return SECSuccess; |
-} |
- |
-SECStatus |
-pkix_pl_HttpDefaultClient_CancelFcn( |
- SEC_HTTP_REQUEST_SESSION request) |
-{ |
- PKIX_Error *err = pkix_pl_HttpDefaultClient_Cancel(request, plContext); |
- |
- if (err) { |
- PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); |
- return SECFailure; |
- } |
- return SECSuccess; |
-} |
- |
-SECStatus |
-pkix_pl_HttpDefaultClient_FreeFcn( |
- SEC_HTTP_REQUEST_SESSION request) |
-{ |
- PKIX_Error *err = |
- PKIX_PL_Object_DecRef((PKIX_PL_Object *)(request), plContext); |
- |
- if (err) { |
- PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); |
- return SECFailure; |
- } |
- return SECSuccess; |
-} |