| OLD | NEW |
| (Empty) |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 4 /* | |
| 5 * pkix_pl_httpdefaultclient.c | |
| 6 * | |
| 7 * HTTPDefaultClient Function Definitions | |
| 8 * | |
| 9 */ | |
| 10 | |
| 11 #include "pkix_pl_httpdefaultclient.h" | |
| 12 | |
| 13 static void *plContext = NULL; | |
| 14 | |
| 15 /* | |
| 16 * The interface specification for an http client requires that it register | |
| 17 * a function table of type SEC_HttpClientFcn, which is defined as a union | |
| 18 * of tables, of which only version 1 is defined at present. | |
| 19 * | |
| 20 * Note: these functions violate the PKIX calling conventions, in that they | |
| 21 * return SECStatus rather than PKIX_Error*, and that they do not provide a | |
| 22 * plContext argument. They are implemented here as calls to PKIX functions, | |
| 23 * but the plContext value is circularly defined - a true kludge. Its value | |
| 24 * is saved at the time of the call to pkix_pl_HttpDefaultClient_Create for | |
| 25 * subsequent use, but since that initial call comes from the | |
| 26 * pkix_pl_HttpDefaultClient_CreateSessionFcn, it's not really getting saved. | |
| 27 */ | |
| 28 static SEC_HttpClientFcnV1 vtable = { | |
| 29 pkix_pl_HttpDefaultClient_CreateSessionFcn, | |
| 30 pkix_pl_HttpDefaultClient_KeepAliveSessionFcn, | |
| 31 pkix_pl_HttpDefaultClient_FreeSessionFcn, | |
| 32 pkix_pl_HttpDefaultClient_RequestCreateFcn, | |
| 33 pkix_pl_HttpDefaultClient_SetPostDataFcn, | |
| 34 pkix_pl_HttpDefaultClient_AddHeaderFcn, | |
| 35 pkix_pl_HttpDefaultClient_TrySendAndReceiveFcn, | |
| 36 pkix_pl_HttpDefaultClient_CancelFcn, | |
| 37 pkix_pl_HttpDefaultClient_FreeFcn | |
| 38 }; | |
| 39 | |
| 40 static SEC_HttpClientFcn httpClient; | |
| 41 | |
| 42 static const char *eohMarker = "\r\n\r\n"; | |
| 43 static const PKIX_UInt32 eohMarkLen = 4; /* strlen(eohMarker) */ | |
| 44 static const char *crlf = "\r\n"; | |
| 45 static const PKIX_UInt32 crlfLen = 2; /* strlen(crlf) */ | |
| 46 static const char *httpprotocol = "HTTP/"; | |
| 47 static const PKIX_UInt32 httpprotocolLen = 5; /* strlen(httpprotocol) */ | |
| 48 | |
| 49 | |
| 50 #define HTTP_UNKNOWN_CONTENT_LENGTH -1 | |
| 51 | |
| 52 /* --Private-HttpDefaultClient-Functions------------------------- */ | |
| 53 | |
| 54 /* | |
| 55 * FUNCTION: pkix_pl_HttpDefaultClient_HdrCheckComplete | |
| 56 * DESCRIPTION: | |
| 57 * | |
| 58 * This function determines whether the headers in the current receive buffer | |
| 59 * in the HttpDefaultClient pointed to by "client" are complete. If so, the | |
| 60 * input data is checked for status code, content-type and content-length are | |
| 61 * extracted, and the client is set up to read the body of the response. | |
| 62 * Otherwise, the client is set up to continue reading header data. | |
| 63 * | |
| 64 * PARAMETERS: | |
| 65 * "client" | |
| 66 * The address of the HttpDefaultClient object. Must be non-NULL. | |
| 67 * "bytesRead" | |
| 68 * The UInt32 number of bytes received in the latest read. | |
| 69 * "pKeepGoing" | |
| 70 * The address at which the Boolean state machine flag is stored to | |
| 71 * indicate whether processing can continue without further input. | |
| 72 * Must be non-NULL. | |
| 73 * "plContext" | |
| 74 * Platform-specific context pointer. | |
| 75 * THREAD SAFETY: | |
| 76 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 77 * RETURNS: | |
| 78 * Returns NULL if the function succeeds. | |
| 79 * Returns a HttpDefaultClient Error if the function fails in a | |
| 80 * non-fatal way. | |
| 81 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 82 */ | |
| 83 static PKIX_Error * | |
| 84 pkix_pl_HttpDefaultClient_HdrCheckComplete( | |
| 85 PKIX_PL_HttpDefaultClient *client, | |
| 86 PKIX_UInt32 bytesRead, | |
| 87 PKIX_Boolean *pKeepGoing, | |
| 88 void *plContext) | |
| 89 { | |
| 90 PKIX_UInt32 alreadyScanned = 0; | |
| 91 PKIX_UInt32 comp = 0; | |
| 92 PKIX_UInt32 headerLength = 0; | |
| 93 PKIX_Int32 contentLength = HTTP_UNKNOWN_CONTENT_LENGTH; | |
| 94 char *eoh = NULL; | |
| 95 char *statusLineEnd = NULL; | |
| 96 char *space = NULL; | |
| 97 char *nextHeader = NULL; | |
| 98 const char *httpcode = NULL; | |
| 99 char *thisHeaderEnd = NULL; | |
| 100 char *value = NULL; | |
| 101 char *colon = NULL; | |
| 102 char *copy = NULL; | |
| 103 char *body = NULL; | |
| 104 | |
| 105 PKIX_ENTER | |
| 106 (HTTPDEFAULTCLIENT, | |
| 107 "pkix_pl_HttpDefaultClient_HdrCheckComplete"); | |
| 108 PKIX_NULLCHECK_TWO(client, pKeepGoing); | |
| 109 | |
| 110 *pKeepGoing = PKIX_FALSE; | |
| 111 | |
| 112 /* Does buffer contain end-of-header marker? */ | |
| 113 | |
| 114 /* Copy number of scanned bytes into a variable. */ | |
| 115 alreadyScanned = client->filledupBytes; | |
| 116 /* | |
| 117 * If this is the initial buffer, we have to scan from the beginning. | |
| 118 * If we scanned, failed to find eohMarker, and read some more, we | |
| 119 * only have to scan from where we left off. | |
| 120 */ | |
| 121 if (alreadyScanned > eohMarkLen) { | |
| 122 /* Back up and restart scanning over a few bytes that were | |
| 123 * scanned before */ | |
| 124 PKIX_UInt32 searchStartPos = alreadyScanned - eohMarkLen; | |
| 125 eoh = PL_strnstr(&(client->rcvBuf[searchStartPos]), eohMarker, | |
| 126 bytesRead + searchStartPos); | |
| 127 } else { | |
| 128 /* A search from the beginning of the buffer. */ | |
| 129 eoh = PL_strnstr(client->rcvBuf, eohMarker, bytesRead); | |
| 130 } | |
| 131 | |
| 132 client->filledupBytes += bytesRead; | |
| 133 | |
| 134 if (eoh == NULL) { /* did we see end-of-header? */ | |
| 135 /* No. Continue to read header data */ | |
| 136 client->connectStatus = HTTP_RECV_HDR; | |
| 137 *pKeepGoing = PKIX_TRUE; | |
| 138 goto cleanup; | |
| 139 } | |
| 140 | |
| 141 /* Yes. Calculate how many bytes in header (not counting eohMarker) */ | |
| 142 headerLength = (eoh - client->rcvBuf); | |
| 143 | |
| 144 /* allocate space to copy header (and for the NULL terminator) */ | |
| 145 PKIX_CHECK(PKIX_PL_Malloc(headerLength + 1, (void **)©, plContext), | |
| 146 PKIX_MALLOCFAILED); | |
| 147 | |
| 148 /* copy header data before we corrupt it (by storing NULLs) */ | |
| 149 PORT_Memcpy(copy, client->rcvBuf, headerLength); | |
| 150 /* Store the NULL terminator */ | |
| 151 copy[headerLength] = '\0'; | |
| 152 client->rcvHeaders = copy; | |
| 153 | |
| 154 /* Did caller want a pointer to header? */ | |
| 155 if (client->rcv_http_headers != NULL) { | |
| 156 /* store pointer for caller */ | |
| 157 *(client->rcv_http_headers) = copy; | |
| 158 } | |
| 159 | |
| 160 /* Check that message status is okay. */ | |
| 161 statusLineEnd = PL_strnstr(client->rcvBuf, crlf, client->capacity); | |
| 162 if (statusLineEnd == NULL) { | |
| 163 client->connectStatus = HTTP_ERROR; | |
| 164 PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); | |
| 165 goto cleanup; | |
| 166 } | |
| 167 | |
| 168 *statusLineEnd = '\0'; | |
| 169 | |
| 170 space = strchr((const char *)client->rcvBuf, ' '); | |
| 171 if (space == NULL) { | |
| 172 client->connectStatus = HTTP_ERROR; | |
| 173 goto cleanup; | |
| 174 } | |
| 175 | |
| 176 comp = PORT_Strncasecmp((const char *)client->rcvBuf, httpprotocol, | |
| 177 httpprotocolLen); | |
| 178 if (comp != 0) { | |
| 179 client->connectStatus = HTTP_ERROR; | |
| 180 goto cleanup; | |
| 181 } | |
| 182 | |
| 183 httpcode = space + 1; | |
| 184 space = strchr(httpcode, ' '); | |
| 185 if (space == NULL) { | |
| 186 client->connectStatus = HTTP_ERROR; | |
| 187 goto cleanup; | |
| 188 } | |
| 189 *space = '\0'; | |
| 190 | |
| 191 client->responseCode = atoi(httpcode); | |
| 192 if (client->responseCode != 200) { | |
| 193 client->connectStatus = HTTP_ERROR; | |
| 194 goto cleanup; | |
| 195 } | |
| 196 | |
| 197 /* Find the content-type and content-length */ | |
| 198 nextHeader = statusLineEnd + crlfLen; | |
| 199 *eoh = '\0'; | |
| 200 do { | |
| 201 thisHeaderEnd = NULL; | |
| 202 value = NULL; | |
| 203 | |
| 204 colon = strchr(nextHeader, ':'); | |
| 205 if (colon == NULL) { | |
| 206 client->connectStatus = HTTP_ERROR; | |
| 207 goto cleanup; | |
| 208 } | |
| 209 *colon = '\0'; | |
| 210 value = colon + 1; | |
| 211 if (*value != ' ') { | |
| 212 client->connectStatus = HTTP_ERROR; | |
| 213 goto cleanup; | |
| 214 } | |
| 215 value++; | |
| 216 thisHeaderEnd = strstr(value, crlf); | |
| 217 if (thisHeaderEnd != NULL) { | |
| 218 *thisHeaderEnd = '\0'; | |
| 219 } | |
| 220 comp = PORT_Strcasecmp(nextHeader, "content-type"); | |
| 221 if (comp == 0) { | |
| 222 client->rcvContentType = PORT_Strdup(value); | |
| 223 } else { | |
| 224 comp = PORT_Strcasecmp(nextHeader, "content-length"); | |
| 225 if (comp == 0) { | |
| 226 contentLength = atoi(value); | |
| 227 } | |
| 228 } | |
| 229 if (thisHeaderEnd != NULL) { | |
| 230 nextHeader = thisHeaderEnd + crlfLen; | |
| 231 } else { | |
| 232 nextHeader = NULL; | |
| 233 } | |
| 234 } while ((nextHeader != NULL) && (nextHeader < (eoh + crlfLen))); | |
| 235 | |
| 236 /* Did caller provide a pointer to return content-type? */ | |
| 237 if (client->rcv_http_content_type != NULL) { | |
| 238 *(client->rcv_http_content_type) = client->rcvContentType; | |
| 239 } | |
| 240 | |
| 241 if (client->rcvContentType == NULL) { | |
| 242 client->connectStatus = HTTP_ERROR; | |
| 243 goto cleanup; | |
| 244 } | |
| 245 | |
| 246 /* How many bytes remain in current buffer, beyond the header? */ | |
| 247 headerLength += eohMarkLen; | |
| 248 client->filledupBytes -= headerLength; | |
| 249 | |
| 250 /* | |
| 251 * The headers have passed validation. Now figure out whether the | |
| 252 * message is within the caller's size limit (if one was specified). | |
| 253 */ | |
| 254 switch (contentLength) { | |
| 255 case 0: | |
| 256 client->rcv_http_data_len = 0; | |
| 257 client->connectStatus = HTTP_COMPLETE; | |
| 258 *pKeepGoing = PKIX_FALSE; | |
| 259 break; | |
| 260 | |
| 261 case HTTP_UNKNOWN_CONTENT_LENGTH: | |
| 262 /* Unknown contentLength indicator.Will be set by | |
| 263 * pkix_pl_HttpDefaultClient_RecvBody whey connection get closed */ | |
| 264 client->rcv_http_data_len = HTTP_UNKNOWN_CONTENT_LENGTH; | |
| 265 contentLength = /* Try to reserve 4K+ buffer */ | |
| 266 client->filledupBytes + HTTP_DATA_BUFSIZE; | |
| 267 if (client->maxResponseLen > 0 && | |
| 268 contentLength > (PKIX_Int32)client->maxResponseLen) { | |
| 269 if (client->filledupBytes < client->maxResponseLen) { | |
| 270 contentLength = client->maxResponseLen; | |
| 271 } else { | |
| 272 client->connectStatus = HTTP_ERROR; | |
| 273 goto cleanup; | |
| 274 } | |
| 275 } | |
| 276 /* set available number of bytes in the buffer */ | |
| 277 client->capacity = contentLength; | |
| 278 client->connectStatus = HTTP_RECV_BODY; | |
| 279 *pKeepGoing = PKIX_TRUE; | |
| 280 break; | |
| 281 | |
| 282 default: | |
| 283 client->rcv_http_data_len = contentLength; | |
| 284 if (client->maxResponseLen > 0 && | |
| 285 (PKIX_Int32)client->maxResponseLen < contentLength) { | |
| 286 client->connectStatus = HTTP_ERROR; | |
| 287 goto cleanup; | |
| 288 } | |
| 289 | |
| 290 /* | |
| 291 * Do we have all of the message body, or do we need to read some m
ore? | |
| 292 */ | |
| 293 if ((PKIX_Int32)client->filledupBytes < contentLength) { | |
| 294 client->connectStatus = HTTP_RECV_BODY; | |
| 295 *pKeepGoing = PKIX_TRUE; | |
| 296 } else { | |
| 297 client->connectStatus = HTTP_COMPLETE; | |
| 298 *pKeepGoing = PKIX_FALSE; | |
| 299 } | |
| 300 } | |
| 301 | |
| 302 if (contentLength > 0) { | |
| 303 /* allocate a buffer of size contentLength for the content */ | |
| 304 PKIX_CHECK(PKIX_PL_Malloc(contentLength, (void **)&body, plContext)
, | |
| 305 PKIX_MALLOCFAILED); | |
| 306 | |
| 307 /* copy any remaining bytes in current buffer into new buffer */ | |
| 308 if (client->filledupBytes > 0) { | |
| 309 PORT_Memcpy(body, &(client->rcvBuf[headerLength]), | |
| 310 client->filledupBytes); | |
| 311 } | |
| 312 } | |
| 313 | |
| 314 PKIX_CHECK(PKIX_PL_Free(client->rcvBuf, plContext), | |
| 315 PKIX_FREEFAILED); | |
| 316 client->rcvBuf = body; | |
| 317 | |
| 318 cleanup: | |
| 319 | |
| 320 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 321 } | |
| 322 | |
| 323 /* | |
| 324 * FUNCTION: PKIX_PL_HttpDefaultClient_Create | |
| 325 * DESCRIPTION: | |
| 326 * | |
| 327 * This function creates a new HttpDefaultClient, and stores the result at | |
| 328 * "pClient". | |
| 329 * | |
| 330 * The HttpClient API does not include a plContext argument in its | |
| 331 * function calls. Its value at the time of this Create call must be the | |
| 332 * same as when the client is invoked. | |
| 333 * | |
| 334 * PARAMETERS: | |
| 335 * "host" | |
| 336 * The name of the server with which we hope to exchange messages. Must | |
| 337 * be non-NULL. | |
| 338 * "portnum" | |
| 339 * The port number to be used for our connection to the server. | |
| 340 * "pClient" | |
| 341 * The address at which the created HttpDefaultClient is to be stored. | |
| 342 * Must be non-NULL. | |
| 343 * "plContext" | |
| 344 * Platform-specific context pointer. | |
| 345 * THREAD SAFETY: | |
| 346 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 347 * RETURNS: | |
| 348 * Returns NULL if the function succeeds. | |
| 349 * Returns a HttpDefaultClient Error if the function fails in | |
| 350 * a non-fatal way. | |
| 351 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 352 */ | |
| 353 static PKIX_Error * | |
| 354 pkix_pl_HttpDefaultClient_Create( | |
| 355 const char *host, | |
| 356 PRUint16 portnum, | |
| 357 PKIX_PL_HttpDefaultClient **pClient, | |
| 358 void *plContext) | |
| 359 { | |
| 360 PKIX_PL_HttpDefaultClient *client = NULL; | |
| 361 | |
| 362 PKIX_ENTER(HTTPDEFAULTCLIENT, "PKIX_PL_HttpDefaultClient_Create"); | |
| 363 PKIX_NULLCHECK_TWO(pClient, host); | |
| 364 | |
| 365 /* allocate an HttpDefaultClient */ | |
| 366 PKIX_CHECK(PKIX_PL_Object_Alloc | |
| 367 (PKIX_HTTPDEFAULTCLIENT_TYPE, | |
| 368 sizeof (PKIX_PL_HttpDefaultClient), | |
| 369 (PKIX_PL_Object **)&client, | |
| 370 plContext), | |
| 371 PKIX_COULDNOTCREATEHTTPDEFAULTCLIENTOBJECT); | |
| 372 | |
| 373 /* Client timeout is overwritten in HttpDefaultClient_RequestCreate | |
| 374 * function. Default value will be ignored. */ | |
| 375 client->timeout = 0; | |
| 376 client->connectStatus = HTTP_NOT_CONNECTED; | |
| 377 client->portnum = portnum; | |
| 378 client->bytesToWrite = 0; | |
| 379 client->send_http_data_len = 0; | |
| 380 client->rcv_http_data_len = 0; | |
| 381 client->capacity = 0; | |
| 382 client->filledupBytes = 0; | |
| 383 client->responseCode = 0; | |
| 384 client->maxResponseLen = 0; | |
| 385 client->GETLen = 0; | |
| 386 client->POSTLen = 0; | |
| 387 client->pRcv_http_data_len = NULL; | |
| 388 client->callbackList = NULL; | |
| 389 client->GETBuf = NULL; | |
| 390 client->POSTBuf = NULL; | |
| 391 client->rcvBuf = NULL; | |
| 392 /* "host" is a parsing result by CERT_GetURL function that adds | |
| 393 * "end of line" to the value. OK to dup the string. */ | |
| 394 client->host = PORT_Strdup(host); | |
| 395 if (!client->host) { | |
| 396 PKIX_ERROR(PKIX_ALLOCERROR); | |
| 397 } | |
| 398 client->path = NULL; | |
| 399 client->rcvContentType = NULL; | |
| 400 client->rcvHeaders = NULL; | |
| 401 client->send_http_method = HTTP_POST_METHOD; | |
| 402 client->send_http_content_type = NULL; | |
| 403 client->send_http_data = NULL; | |
| 404 client->rcv_http_response_code = NULL; | |
| 405 client->rcv_http_content_type = NULL; | |
| 406 client->rcv_http_headers = NULL; | |
| 407 client->rcv_http_data = NULL; | |
| 408 client->socket = NULL; | |
| 409 | |
| 410 /* | |
| 411 * The HttpClient API does not include a plContext argument in its | |
| 412 * function calls. Save it here. | |
| 413 */ | |
| 414 client->plContext = plContext; | |
| 415 | |
| 416 *pClient = client; | |
| 417 | |
| 418 cleanup: | |
| 419 if (PKIX_ERROR_RECEIVED) { | |
| 420 PKIX_DECREF(client); | |
| 421 } | |
| 422 | |
| 423 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 424 } | |
| 425 | |
| 426 /* | |
| 427 * FUNCTION: pkix_pl_HttpDefaultClient_Destroy | |
| 428 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
| 429 */ | |
| 430 static PKIX_Error * | |
| 431 pkix_pl_HttpDefaultClient_Destroy( | |
| 432 PKIX_PL_Object *object, | |
| 433 void *plContext) | |
| 434 { | |
| 435 PKIX_PL_HttpDefaultClient *client = NULL; | |
| 436 | |
| 437 PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Destroy"); | |
| 438 PKIX_NULLCHECK_ONE(object); | |
| 439 | |
| 440 PKIX_CHECK(pkix_CheckType | |
| 441 (object, PKIX_HTTPDEFAULTCLIENT_TYPE, plContext), | |
| 442 PKIX_OBJECTNOTANHTTPDEFAULTCLIENT); | |
| 443 | |
| 444 client = (PKIX_PL_HttpDefaultClient *)object; | |
| 445 | |
| 446 if (client->rcvHeaders) { | |
| 447 PKIX_PL_Free(client->rcvHeaders, plContext); | |
| 448 client->rcvHeaders = NULL; | |
| 449 } | |
| 450 if (client->rcvContentType) { | |
| 451 PORT_Free(client->rcvContentType); | |
| 452 client->rcvContentType = NULL; | |
| 453 } | |
| 454 if (client->GETBuf != NULL) { | |
| 455 PR_smprintf_free(client->GETBuf); | |
| 456 client->GETBuf = NULL; | |
| 457 } | |
| 458 if (client->POSTBuf != NULL) { | |
| 459 PKIX_PL_Free(client->POSTBuf, plContext); | |
| 460 client->POSTBuf = NULL; | |
| 461 } | |
| 462 if (client->rcvBuf != NULL) { | |
| 463 PKIX_PL_Free(client->rcvBuf, plContext); | |
| 464 client->rcvBuf = NULL; | |
| 465 } | |
| 466 if (client->host) { | |
| 467 PORT_Free(client->host); | |
| 468 client->host = NULL; | |
| 469 } | |
| 470 if (client->path) { | |
| 471 PORT_Free(client->path); | |
| 472 client->path = NULL; | |
| 473 } | |
| 474 PKIX_DECREF(client->socket); | |
| 475 | |
| 476 cleanup: | |
| 477 | |
| 478 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 479 } | |
| 480 | |
| 481 /* | |
| 482 * FUNCTION: pkix_pl_HttpDefaultClient_RegisterSelf | |
| 483 * | |
| 484 * DESCRIPTION: | |
| 485 * Registers PKIX_PL_HTTPDEFAULTCLIENT_TYPE and its related | |
| 486 * functions with systemClasses[] | |
| 487 * | |
| 488 * THREAD SAFETY: | |
| 489 * Not Thread Safe - for performance and complexity reasons | |
| 490 * | |
| 491 * Since this function is only called by PKIX_PL_Initialize, which should | |
| 492 * only be called once, it is acceptable that this function is not | |
| 493 * thread-safe. | |
| 494 */ | |
| 495 PKIX_Error * | |
| 496 pkix_pl_HttpDefaultClient_RegisterSelf(void *plContext) | |
| 497 { | |
| 498 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
| 499 pkix_ClassTable_Entry *entry = | |
| 500 &systemClasses[PKIX_HTTPDEFAULTCLIENT_TYPE]; | |
| 501 | |
| 502 PKIX_ENTER(HTTPDEFAULTCLIENT, | |
| 503 "pkix_pl_HttpDefaultClient_RegisterSelf"); | |
| 504 | |
| 505 entry->description = "HttpDefaultClient"; | |
| 506 entry->typeObjectSize = sizeof(PKIX_PL_HttpDefaultClient); | |
| 507 entry->destructor = pkix_pl_HttpDefaultClient_Destroy; | |
| 508 | |
| 509 httpClient.version = 1; | |
| 510 httpClient.fcnTable.ftable1 = vtable; | |
| 511 (void)SEC_RegisterDefaultHttpClient(&httpClient); | |
| 512 | |
| 513 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 514 } | |
| 515 | |
| 516 /* --Private-HttpDefaultClient-I/O-Functions---------------------------- */ | |
| 517 /* | |
| 518 * FUNCTION: pkix_pl_HttpDefaultClient_ConnectContinue | |
| 519 * DESCRIPTION: | |
| 520 * | |
| 521 * This function determines whether a socket Connect initiated earlier for the | |
| 522 * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a flag | |
| 523 * indicating whether processing can continue without further input. | |
| 524 * | |
| 525 * PARAMETERS: | |
| 526 * "client" | |
| 527 * The address of the HttpDefaultClient object. Must be non-NULL. | |
| 528 * "pKeepGoing" | |
| 529 * The address at which the Boolean state machine flag is stored to | |
| 530 * indicate whether processing can continue without further input. | |
| 531 * Must be non-NULL. | |
| 532 * "plContext" | |
| 533 * Platform-specific context pointer. | |
| 534 * THREAD SAFETY: | |
| 535 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 536 * RETURNS: | |
| 537 * Returns NULL if the function succeeds. | |
| 538 * Returns a HttpDefaultClient Error if the function fails in a | |
| 539 * non-fatal way. | |
| 540 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 541 */ | |
| 542 static PKIX_Error * | |
| 543 pkix_pl_HttpDefaultClient_ConnectContinue( | |
| 544 PKIX_PL_HttpDefaultClient *client, | |
| 545 PKIX_Boolean *pKeepGoing, | |
| 546 void *plContext) | |
| 547 { | |
| 548 PRErrorCode status; | |
| 549 PKIX_Boolean keepGoing = PKIX_FALSE; | |
| 550 PKIX_PL_Socket_Callback *callbackList = NULL; | |
| 551 | |
| 552 PKIX_ENTER | |
| 553 (HTTPDEFAULTCLIENT, | |
| 554 "pkix_pl_HttpDefaultClient_ConnectContinue"); | |
| 555 PKIX_NULLCHECK_ONE(client); | |
| 556 | |
| 557 callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; | |
| 558 | |
| 559 PKIX_CHECK(callbackList->connectcontinueCallback | |
| 560 (client->socket, &status, plContext), | |
| 561 PKIX_SOCKETCONNECTCONTINUEFAILED); | |
| 562 | |
| 563 if (status == 0) { | |
| 564 client->connectStatus = HTTP_CONNECTED; | |
| 565 keepGoing = PKIX_TRUE; | |
| 566 } else if (status != PR_IN_PROGRESS_ERROR) { | |
| 567 PKIX_ERROR(PKIX_UNEXPECTEDERRORINESTABLISHINGCONNECTION); | |
| 568 } | |
| 569 | |
| 570 *pKeepGoing = keepGoing; | |
| 571 | |
| 572 cleanup: | |
| 573 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 574 } | |
| 575 | |
| 576 /* | |
| 577 * FUNCTION: pkix_pl_HttpDefaultClient_Send | |
| 578 * DESCRIPTION: | |
| 579 * | |
| 580 * This function creates and sends HTTP-protocol headers and, if applicable, | |
| 581 * data, for the HttpDefaultClient "client", and stores in "pKeepGoing" a flag | |
| 582 * indicating whether processing can continue without further input, and at | |
| 583 * "pBytesTransferred" the number of bytes sent. | |
| 584 * | |
| 585 * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use | |
| 586 * and that transmission has not completed. | |
| 587 * | |
| 588 * PARAMETERS: | |
| 589 * "client" | |
| 590 * The address of the HttpDefaultClient object. Must be non-NULL. | |
| 591 * "pKeepGoing" | |
| 592 * The address at which the Boolean state machine flag is stored to | |
| 593 * indicate whether processing can continue without further input. | |
| 594 * Must be non-NULL. | |
| 595 * "pBytesTransferred" | |
| 596 * The address at which the number of bytes sent is stored. Must be | |
| 597 * non-NULL. | |
| 598 * "plContext" | |
| 599 * Platform-specific context pointer. | |
| 600 * THREAD SAFETY: | |
| 601 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 602 * RETURNS: | |
| 603 * Returns NULL if the function succeeds. | |
| 604 * Returns a HttpDefaultClient Error if the function fails in a | |
| 605 * non-fatal way. | |
| 606 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 607 */ | |
| 608 static PKIX_Error * | |
| 609 pkix_pl_HttpDefaultClient_Send( | |
| 610 PKIX_PL_HttpDefaultClient *client, | |
| 611 PKIX_Boolean *pKeepGoing, | |
| 612 PKIX_UInt32 *pBytesTransferred, | |
| 613 void *plContext) | |
| 614 { | |
| 615 PKIX_Int32 bytesWritten = 0; | |
| 616 PKIX_Int32 lenToWrite = 0; | |
| 617 PKIX_PL_Socket_Callback *callbackList = NULL; | |
| 618 char *dataToWrite = NULL; | |
| 619 | |
| 620 PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Send"); | |
| 621 PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred); | |
| 622 | |
| 623 *pKeepGoing = PKIX_FALSE; | |
| 624 | |
| 625 /* Do we have anything waiting to go? */ | |
| 626 if ((client->GETBuf) || (client->POSTBuf)) { | |
| 627 | |
| 628 if (client->GETBuf) { | |
| 629 dataToWrite = client->GETBuf; | |
| 630 lenToWrite = client->GETLen; | |
| 631 } else { | |
| 632 dataToWrite = client->POSTBuf; | |
| 633 lenToWrite = client->POSTLen; | |
| 634 } | |
| 635 | |
| 636 callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; | |
| 637 | |
| 638 PKIX_CHECK(callbackList->sendCallback | |
| 639 (client->socket, | |
| 640 dataToWrite, | |
| 641 lenToWrite, | |
| 642 &bytesWritten, | |
| 643 plContext), | |
| 644 PKIX_SOCKETSENDFAILED); | |
| 645 | |
| 646 client->rcvBuf = NULL; | |
| 647 client->capacity = 0; | |
| 648 client->filledupBytes = 0; | |
| 649 | |
| 650 /* | |
| 651 * If the send completed we can proceed to try for the | |
| 652 * response. If the send did not complete we will have | |
| 653 * to poll for completion later. | |
| 654 */ | |
| 655 if (bytesWritten >= 0) { | |
| 656 client->connectStatus = HTTP_RECV_HDR; | |
| 657 *pKeepGoing = PKIX_TRUE; | |
| 658 } else { | |
| 659 client->connectStatus = HTTP_SEND_PENDING; | |
| 660 *pKeepGoing = PKIX_FALSE; | |
| 661 } | |
| 662 | |
| 663 } | |
| 664 | |
| 665 *pBytesTransferred = bytesWritten; | |
| 666 | |
| 667 cleanup: | |
| 668 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 669 } | |
| 670 | |
| 671 /* | |
| 672 * FUNCTION: pkix_pl_HttpDefaultClient_SendContinue | |
| 673 * DESCRIPTION: | |
| 674 * | |
| 675 * This function determines whether the sending of the HTTP message for the | |
| 676 * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a | |
| 677 * flag indicating whether processing can continue without further input, and | |
| 678 * at "pBytesTransferred" the number of bytes sent. | |
| 679 * | |
| 680 * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use | |
| 681 * and that transmission has not completed. | |
| 682 * | |
| 683 * PARAMETERS: | |
| 684 * "client" | |
| 685 * The address of the HttpDefaultClient object. Must be non-NULL. | |
| 686 * "pKeepGoing" | |
| 687 * The address at which the Boolean state machine flag is stored to | |
| 688 * indicate whether processing can continue without further input. | |
| 689 * Must be non-NULL. | |
| 690 * "pBytesTransferred" | |
| 691 * The address at which the number of bytes sent is stored. Must be | |
| 692 * non-NULL. | |
| 693 * "plContext" | |
| 694 * Platform-specific context pointer. | |
| 695 * THREAD SAFETY: | |
| 696 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 697 * RETURNS: | |
| 698 * Returns NULL if the function succeeds. | |
| 699 * Returns a HttpDefaultClient Error if the function fails in a | |
| 700 * non-fatal way. | |
| 701 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 702 */ | |
| 703 static PKIX_Error * | |
| 704 pkix_pl_HttpDefaultClient_SendContinue( | |
| 705 PKIX_PL_HttpDefaultClient *client, | |
| 706 PKIX_Boolean *pKeepGoing, | |
| 707 PKIX_UInt32 *pBytesTransferred, | |
| 708 void *plContext) | |
| 709 { | |
| 710 PKIX_Int32 bytesWritten = 0; | |
| 711 PKIX_PL_Socket_Callback *callbackList = NULL; | |
| 712 | |
| 713 PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_SendContinue"); | |
| 714 PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred); | |
| 715 | |
| 716 *pKeepGoing = PKIX_FALSE; | |
| 717 | |
| 718 callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; | |
| 719 | |
| 720 PKIX_CHECK(callbackList->pollCallback | |
| 721 (client->socket, &bytesWritten, NULL, plContext), | |
| 722 PKIX_SOCKETPOLLFAILED); | |
| 723 | |
| 724 /* | |
| 725 * If the send completed we can proceed to try for the | |
| 726 * response. If the send did not complete we will have | |
| 727 * continue to poll. | |
| 728 */ | |
| 729 if (bytesWritten >= 0) { | |
| 730 client->connectStatus = HTTP_RECV_HDR; | |
| 731 *pKeepGoing = PKIX_TRUE; | |
| 732 } | |
| 733 | |
| 734 *pBytesTransferred = bytesWritten; | |
| 735 | |
| 736 cleanup: | |
| 737 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 738 } | |
| 739 | |
| 740 /* | |
| 741 * FUNCTION: pkix_pl_HttpDefaultClient_RecvHdr | |
| 742 * DESCRIPTION: | |
| 743 * | |
| 744 * This function receives HTTP headers for the HttpDefaultClient "client", and | |
| 745 * stores in "pKeepGoing" a flag indicating whether processing can continue | |
| 746 * without further input. | |
| 747 * | |
| 748 * PARAMETERS: | |
| 749 * "client" | |
| 750 * The address of the HttpDefaultClient object. Must be non-NULL. | |
| 751 * "pKeepGoing" | |
| 752 * The address at which the Boolean state machine flag is stored to | |
| 753 * indicate whether processing can continue without further input. | |
| 754 * Must be non-NULL. | |
| 755 * "plContext" | |
| 756 * Platform-specific context pointer. | |
| 757 * THREAD SAFETY: | |
| 758 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 759 * RETURNS: | |
| 760 * Returns NULL if the function succeeds. | |
| 761 * Returns a HttpDefaultClient Error if the function fails in a | |
| 762 * non-fatal way. | |
| 763 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 764 */ | |
| 765 static PKIX_Error * | |
| 766 pkix_pl_HttpDefaultClient_RecvHdr( | |
| 767 PKIX_PL_HttpDefaultClient *client, | |
| 768 PKIX_Boolean *pKeepGoing, | |
| 769 void *plContext) | |
| 770 { | |
| 771 PKIX_UInt32 bytesToRead = 0; | |
| 772 PKIX_Int32 bytesRead = 0; | |
| 773 PKIX_PL_Socket_Callback *callbackList = NULL; | |
| 774 | |
| 775 PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RecvHdr"); | |
| 776 PKIX_NULLCHECK_TWO(client, pKeepGoing); | |
| 777 | |
| 778 /* | |
| 779 * rcvbuf, capacity, and filledupBytes were | |
| 780 * initialized when we wrote the headers. We begin by reading | |
| 781 * HTTP_HEADER_BUFSIZE bytes, repeatedly increasing the buffersize and | |
| 782 * reading again if necessary, until we have read the end-of-header | |
| 783 * marker, "\r\n\r\n", or have reached our maximum. | |
| 784 */ | |
| 785 client->capacity += HTTP_HEADER_BUFSIZE; | |
| 786 PKIX_CHECK(PKIX_PL_Realloc | |
| 787 (client->rcvBuf, | |
| 788 client->capacity, | |
| 789 (void **)&(client->rcvBuf), | |
| 790 plContext), | |
| 791 PKIX_REALLOCFAILED); | |
| 792 | |
| 793 bytesToRead = client->capacity - client->filledupBytes; | |
| 794 | |
| 795 callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; | |
| 796 | |
| 797 PKIX_CHECK(callbackList->recvCallback | |
| 798 (client->socket, | |
| 799 (void *)&(client->rcvBuf[client->filledupBytes]), | |
| 800 bytesToRead, | |
| 801 &bytesRead, | |
| 802 plContext), | |
| 803 PKIX_SOCKETRECVFAILED); | |
| 804 | |
| 805 if (bytesRead > 0) { | |
| 806 /* client->filledupBytes will be adjusted by | |
| 807 * pkix_pl_HttpDefaultClient_HdrCheckComplete */ | |
| 808 PKIX_CHECK( | |
| 809 pkix_pl_HttpDefaultClient_HdrCheckComplete(client, bytesRead, | |
| 810 pKeepGoing, | |
| 811 plContext), | |
| 812 PKIX_HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED); | |
| 813 } else { | |
| 814 client->connectStatus = HTTP_RECV_HDR_PENDING; | |
| 815 *pKeepGoing = PKIX_FALSE; | |
| 816 } | |
| 817 | |
| 818 cleanup: | |
| 819 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 820 } | |
| 821 | |
| 822 /* | |
| 823 * FUNCTION: pkix_pl_HttpDefaultClient_RecvHdrContinue | |
| 824 * DESCRIPTION: | |
| 825 * | |
| 826 * This function determines whether the receiving of the HTTP headers for the | |
| 827 * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a flag | |
| 828 * indicating whether processing can continue without further input. | |
| 829 * | |
| 830 * PARAMETERS: | |
| 831 * "client" | |
| 832 * The address of the HttpDefaultClient object. Must be non-NULL. | |
| 833 * "pKeepGoing" | |
| 834 * The address at which the Boolean state machine flag is stored to | |
| 835 * indicate whether processing can continue without further input. | |
| 836 * Must be non-NULL. | |
| 837 * "plContext" | |
| 838 * Platform-specific context pointer. | |
| 839 * THREAD SAFETY: | |
| 840 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 841 * RETURNS: | |
| 842 * Returns NULL if the function succeeds. | |
| 843 * Returns a HttpDefaultClient Error if the function fails in a | |
| 844 * non-fatal way. | |
| 845 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 846 */ | |
| 847 static PKIX_Error * | |
| 848 pkix_pl_HttpDefaultClient_RecvHdrContinue( | |
| 849 PKIX_PL_HttpDefaultClient *client, | |
| 850 PKIX_Boolean *pKeepGoing, | |
| 851 void *plContext) | |
| 852 { | |
| 853 PKIX_Int32 bytesRead = 0; | |
| 854 PKIX_PL_Socket_Callback *callbackList = NULL; | |
| 855 | |
| 856 PKIX_ENTER | |
| 857 (HTTPDEFAULTCLIENT, | |
| 858 "pkix_pl_HttpDefaultClient_RecvHdrContinue"); | |
| 859 PKIX_NULLCHECK_TWO(client, pKeepGoing); | |
| 860 | |
| 861 callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; | |
| 862 | |
| 863 PKIX_CHECK(callbackList->pollCallback | |
| 864 (client->socket, NULL, &bytesRead, plContext), | |
| 865 PKIX_SOCKETPOLLFAILED); | |
| 866 | |
| 867 if (bytesRead > 0) { | |
| 868 client->filledupBytes += bytesRead; | |
| 869 | |
| 870 PKIX_CHECK(pkix_pl_HttpDefaultClient_HdrCheckComplete | |
| 871 (client, bytesRead, pKeepGoing, plContext), | |
| 872 PKIX_HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED); | |
| 873 | |
| 874 } else { | |
| 875 | |
| 876 *pKeepGoing = PKIX_FALSE; | |
| 877 | |
| 878 } | |
| 879 | |
| 880 cleanup: | |
| 881 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 882 } | |
| 883 | |
| 884 /* | |
| 885 * FUNCTION: pkix_pl_HttpDefaultClient_RecvBody | |
| 886 * DESCRIPTION: | |
| 887 * | |
| 888 * This function processes the contents of the first buffer of a received | |
| 889 * HTTP-protocol message for the HttpDefaultClient "client", and stores in | |
| 890 * "pKeepGoing" a flag indicating whether processing can continue without | |
| 891 * further input. | |
| 892 * | |
| 893 * PARAMETERS: | |
| 894 * "client" | |
| 895 * The address of the HttpDefaultClient object. Must be non-NULL. | |
| 896 * "pKeepGoing" | |
| 897 * The address at which the Boolean state machine flag is stored to | |
| 898 * indicate whether processing can continue without further input. | |
| 899 * Must be non-NULL. | |
| 900 * "plContext" | |
| 901 * Platform-specific context pointer. | |
| 902 * THREAD SAFETY: | |
| 903 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 904 * RETURNS: | |
| 905 * Returns NULL if the function succeeds. | |
| 906 * Returns a HttpDefaultClient Error if the function fails in a | |
| 907 * non-fatal way. | |
| 908 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 909 */ | |
| 910 static PKIX_Error * | |
| 911 pkix_pl_HttpDefaultClient_RecvBody( | |
| 912 PKIX_PL_HttpDefaultClient *client, | |
| 913 PKIX_Boolean *pKeepGoing, | |
| 914 void *plContext) | |
| 915 { | |
| 916 PKIX_Int32 bytesRead = 0; | |
| 917 PKIX_Int32 bytesToRead = 0; | |
| 918 PKIX_PL_Socket_Callback *callbackList = NULL; | |
| 919 | |
| 920 PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RecvBody"); | |
| 921 PKIX_NULLCHECK_TWO(client, pKeepGoing); | |
| 922 | |
| 923 callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; | |
| 924 | |
| 925 if (client->rcv_http_data_len != HTTP_UNKNOWN_CONTENT_LENGTH) { | |
| 926 bytesToRead = client->rcv_http_data_len - | |
| 927 client->filledupBytes; | |
| 928 } else { | |
| 929 /* Reading till the EOF. Context length is not known.*/ | |
| 930 /* Check the buffer capacity: increase and | |
| 931 * reallocate if it is low. */ | |
| 932 int freeBuffSize = client->capacity - client->filledupBytes; | |
| 933 if (freeBuffSize < HTTP_MIN_AVAILABLE_BUFFER_SIZE) { | |
| 934 /* New length will be consist of available(downloaded) bytes, | |
| 935 * plus remaining capacity, plus new expansion. */ | |
| 936 int currBuffSize = client->capacity; | |
| 937 /* Try to increase the buffer by 4K */ | |
| 938 unsigned int newLength = currBuffSize + HTTP_DATA_BUFSIZE; | |
| 939 if (client->maxResponseLen > 0 && | |
| 940 newLength > client->maxResponseLen) { | |
| 941 newLength = client->maxResponseLen; | |
| 942 } | |
| 943 /* Check if we can grow the buffer and report an error if | |
| 944 * new size is not larger than the current size of the buffer.*/ | |
| 945 if (newLength <= client->filledupBytes) { | |
| 946 client->rcv_http_data_len = client->filledupBytes; | |
| 947 client->connectStatus = HTTP_ERROR; | |
| 948 *pKeepGoing = PKIX_FALSE; | |
| 949 goto cleanup; | |
| 950 } | |
| 951 if (client->capacity < newLength) { | |
| 952 client->capacity = newLength; | |
| 953 PKIX_CHECK( | |
| 954 PKIX_PL_Realloc(client->rcvBuf, newLength, | |
| 955 (void**)&client->rcvBuf, plContext), | |
| 956 PKIX_REALLOCFAILED); | |
| 957 freeBuffSize = client->capacity - | |
| 958 client->filledupBytes; | |
| 959 } | |
| 960 } | |
| 961 bytesToRead = freeBuffSize; | |
| 962 } | |
| 963 | |
| 964 /* Use poll callback if waiting on non-blocking IO */ | |
| 965 if (client->connectStatus == HTTP_RECV_BODY_PENDING) { | |
| 966 PKIX_CHECK(callbackList->pollCallback | |
| 967 (client->socket, NULL, &bytesRead, plContext), | |
| 968 PKIX_SOCKETPOLLFAILED); | |
| 969 } else { | |
| 970 PKIX_CHECK(callbackList->recvCallback | |
| 971 (client->socket, | |
| 972 (void *)&(client->rcvBuf[client->filledupBytes]), | |
| 973 bytesToRead, | |
| 974 &bytesRead, | |
| 975 plContext), | |
| 976 PKIX_SOCKETRECVFAILED); | |
| 977 } | |
| 978 | |
| 979 /* If bytesRead < 0, an error will be thrown by recvCallback, so | |
| 980 * need to handle >= 0 cases. */ | |
| 981 | |
| 982 /* bytesRead == 0 - IO was blocked. */ | |
| 983 if (bytesRead == 0) { | |
| 984 client->connectStatus = HTTP_RECV_BODY_PENDING; | |
| 985 *pKeepGoing = PKIX_TRUE; | |
| 986 goto cleanup; | |
| 987 } | |
| 988 | |
| 989 /* We got something. Did we get it all? */ | |
| 990 client->filledupBytes += bytesRead; | |
| 991 | |
| 992 /* continue if not enough bytes read or if complete size of | |
| 993 * transfer is unknown */ | |
| 994 if (bytesToRead > bytesRead || | |
| 995 client->rcv_http_data_len == HTTP_UNKNOWN_CONTENT_LENGTH) { | |
| 996 *pKeepGoing = PKIX_TRUE; | |
| 997 goto cleanup; | |
| 998 } | |
| 999 client->connectStatus = HTTP_COMPLETE; | |
| 1000 *pKeepGoing = PKIX_FALSE; | |
| 1001 | |
| 1002 cleanup: | |
| 1003 if (pkixErrorResult && pkixErrorResult->errCode == | |
| 1004 PKIX_PRRECVREPORTSNETWORKCONNECTIONCLOSED) { | |
| 1005 if (client->rcv_http_data_len == HTTP_UNKNOWN_CONTENT_LENGTH) { | |
| 1006 client->rcv_http_data_len = client->filledupBytes; | |
| 1007 client->connectStatus = HTTP_COMPLETE; | |
| 1008 *pKeepGoing = PKIX_FALSE; | |
| 1009 PKIX_DECREF(pkixErrorResult); | |
| 1010 } else { | |
| 1011 client->connectStatus = HTTP_ERROR; | |
| 1012 } | |
| 1013 } | |
| 1014 | |
| 1015 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 1016 } | |
| 1017 | |
| 1018 /* | |
| 1019 * FUNCTION: pkix_pl_HttpDefaultClient_Dispatch | |
| 1020 * DESCRIPTION: | |
| 1021 * | |
| 1022 * This function is the state machine dispatcher for the HttpDefaultClient | |
| 1023 * pointed to by "client". Results are returned by changes to various fields | |
| 1024 * in the context. | |
| 1025 * | |
| 1026 * PARAMETERS: | |
| 1027 * "client" | |
| 1028 * The address of the HttpDefaultClient object. Must be non-NULL. | |
| 1029 * "plContext" | |
| 1030 * Platform-specific context pointer. | |
| 1031 * THREAD SAFETY: | |
| 1032 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 1033 * RETURNS: | |
| 1034 * Returns NULL if the function succeeds. | |
| 1035 * Returns a HttpDefaultClient Error if the function fails in a | |
| 1036 * non-fatal way. | |
| 1037 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 1038 */ | |
| 1039 static PKIX_Error * | |
| 1040 pkix_pl_HttpDefaultClient_Dispatch( | |
| 1041 PKIX_PL_HttpDefaultClient *client, | |
| 1042 void *plContext) | |
| 1043 { | |
| 1044 PKIX_UInt32 bytesTransferred = 0; | |
| 1045 PKIX_Boolean keepGoing = PKIX_TRUE; | |
| 1046 | |
| 1047 PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Dispatch"); | |
| 1048 PKIX_NULLCHECK_ONE(client); | |
| 1049 | |
| 1050 while (keepGoing) { | |
| 1051 switch (client->connectStatus) { | |
| 1052 case HTTP_CONNECT_PENDING: | |
| 1053 PKIX_CHECK(pkix_pl_HttpDefaultClient_ConnectContinue | |
| 1054 (client, &keepGoing, plContext), | |
| 1055 PKIX_HTTPDEFAULTCLIENTCONNECTCONTINUEFAILED); | |
| 1056 break; | |
| 1057 case HTTP_CONNECTED: | |
| 1058 PKIX_CHECK(pkix_pl_HttpDefaultClient_Send | |
| 1059 (client, &keepGoing, &bytesTransferred, plContext), | |
| 1060 PKIX_HTTPDEFAULTCLIENTSENDFAILED); | |
| 1061 break; | |
| 1062 case HTTP_SEND_PENDING: | |
| 1063 PKIX_CHECK(pkix_pl_HttpDefaultClient_SendContinue | |
| 1064 (client, &keepGoing, &bytesTransferred, plContext), | |
| 1065 PKIX_HTTPDEFAULTCLIENTSENDCONTINUEFAILED); | |
| 1066 break; | |
| 1067 case HTTP_RECV_HDR: | |
| 1068 PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvHdr | |
| 1069 (client, &keepGoing, plContext), | |
| 1070 PKIX_HTTPDEFAULTCLIENTRECVHDRFAILED); | |
| 1071 break; | |
| 1072 case HTTP_RECV_HDR_PENDING: | |
| 1073 PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvHdrContinue | |
| 1074 (client, &keepGoing, plContext), | |
| 1075 PKIX_HTTPDEFAULTCLIENTRECVHDRCONTINUEFAILED); | |
| 1076 break; | |
| 1077 case HTTP_RECV_BODY: | |
| 1078 case HTTP_RECV_BODY_PENDING: | |
| 1079 PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvBody | |
| 1080 (client, &keepGoing, plContext), | |
| 1081 PKIX_HTTPDEFAULTCLIENTRECVBODYFAILED); | |
| 1082 break; | |
| 1083 case HTTP_ERROR: | |
| 1084 case HTTP_COMPLETE: | |
| 1085 keepGoing = PKIX_FALSE; | |
| 1086 break; | |
| 1087 case HTTP_NOT_CONNECTED: | |
| 1088 default: | |
| 1089 PKIX_ERROR(PKIX_HTTPDEFAULTCLIENTINILLEGALSTATE); | |
| 1090 } | |
| 1091 } | |
| 1092 | |
| 1093 cleanup: | |
| 1094 | |
| 1095 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 1096 } | |
| 1097 | |
| 1098 /* | |
| 1099 * --HttpClient vtable functions | |
| 1100 * See comments in ocspt.h for the function (wrappers) that return SECStatus. | |
| 1101 * The functions that return PKIX_Error* are the libpkix implementations. | |
| 1102 */ | |
| 1103 | |
| 1104 PKIX_Error * | |
| 1105 pkix_pl_HttpDefaultClient_CreateSession( | |
| 1106 const char *host, | |
| 1107 PRUint16 portnum, | |
| 1108 SEC_HTTP_SERVER_SESSION *pSession, | |
| 1109 void *plContext) | |
| 1110 { | |
| 1111 PKIX_PL_HttpDefaultClient *client = NULL; | |
| 1112 | |
| 1113 PKIX_ENTER | |
| 1114 (HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_CreateSession"); | |
| 1115 PKIX_NULLCHECK_TWO(host, pSession); | |
| 1116 | |
| 1117 PKIX_CHECK(pkix_pl_HttpDefaultClient_Create | |
| 1118 (host, portnum, &client, plContext), | |
| 1119 PKIX_HTTPDEFAULTCLIENTCREATEFAILED); | |
| 1120 | |
| 1121 *pSession = (SEC_HTTP_SERVER_SESSION)client; | |
| 1122 | |
| 1123 cleanup: | |
| 1124 | |
| 1125 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 1126 | |
| 1127 } | |
| 1128 | |
| 1129 PKIX_Error * | |
| 1130 pkix_pl_HttpDefaultClient_KeepAliveSession( | |
| 1131 SEC_HTTP_SERVER_SESSION session, | |
| 1132 PRPollDesc **pPollDesc, | |
| 1133 void *plContext) | |
| 1134 { | |
| 1135 PKIX_ENTER | |
| 1136 (HTTPDEFAULTCLIENT, | |
| 1137 "pkix_pl_HttpDefaultClient_KeepAliveSession"); | |
| 1138 PKIX_NULLCHECK_TWO(session, pPollDesc); | |
| 1139 | |
| 1140 PKIX_CHECK(pkix_CheckType | |
| 1141 ((PKIX_PL_Object *)session, | |
| 1142 PKIX_HTTPDEFAULTCLIENT_TYPE, | |
| 1143 plContext), | |
| 1144 PKIX_SESSIONNOTANHTTPDEFAULTCLIENT); | |
| 1145 | |
| 1146 /* XXX Not implemented */ | |
| 1147 | |
| 1148 cleanup: | |
| 1149 | |
| 1150 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 1151 | |
| 1152 } | |
| 1153 | |
| 1154 PKIX_Error * | |
| 1155 pkix_pl_HttpDefaultClient_RequestCreate( | |
| 1156 SEC_HTTP_SERVER_SESSION session, | |
| 1157 const char *http_protocol_variant, /* usually "http" */ | |
| 1158 const char *path_and_query_string, | |
| 1159 const char *http_request_method, | |
| 1160 const PRIntervalTime timeout, | |
| 1161 SEC_HTTP_REQUEST_SESSION *pRequest, | |
| 1162 void *plContext) | |
| 1163 { | |
| 1164 PKIX_PL_HttpDefaultClient *client = NULL; | |
| 1165 PKIX_PL_Socket *socket = NULL; | |
| 1166 PKIX_PL_Socket_Callback *callbackList = NULL; | |
| 1167 PRFileDesc *fileDesc = NULL; | |
| 1168 PRErrorCode status = 0; | |
| 1169 | |
| 1170 PKIX_ENTER | |
| 1171 (HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RequestCreate"); | |
| 1172 PKIX_NULLCHECK_TWO(session, pRequest); | |
| 1173 | |
| 1174 PKIX_CHECK(pkix_CheckType | |
| 1175 ((PKIX_PL_Object *)session, | |
| 1176 PKIX_HTTPDEFAULTCLIENT_TYPE, | |
| 1177 plContext), | |
| 1178 PKIX_SESSIONNOTANHTTPDEFAULTCLIENT); | |
| 1179 | |
| 1180 client = (PKIX_PL_HttpDefaultClient *)session; | |
| 1181 | |
| 1182 /* We only know how to do http */ | |
| 1183 if (PORT_Strncasecmp(http_protocol_variant, "http", 4) != 0) { | |
| 1184 PKIX_ERROR(PKIX_UNRECOGNIZEDPROTOCOLREQUESTED); | |
| 1185 } | |
| 1186 | |
| 1187 if (PORT_Strncasecmp(http_request_method, "POST", 4) == 0) { | |
| 1188 client->send_http_method = HTTP_POST_METHOD; | |
| 1189 } else if (PORT_Strncasecmp(http_request_method, "GET", 3) == 0) { | |
| 1190 client->send_http_method = HTTP_GET_METHOD; | |
| 1191 } else { | |
| 1192 /* We only know how to do POST and GET */ | |
| 1193 PKIX_ERROR(PKIX_UNRECOGNIZEDREQUESTMETHOD); | |
| 1194 } | |
| 1195 | |
| 1196 if (path_and_query_string) { | |
| 1197 /* "path_and_query_string" is a parsing result by CERT_GetURL | |
| 1198 * function that adds "end of line" to the value. OK to dup | |
| 1199 * the string. */ | |
| 1200 client->path = PORT_Strdup(path_and_query_string); | |
| 1201 if (!client->path) { | |
| 1202 PKIX_ERROR(PKIX_ALLOCERROR); | |
| 1203 } | |
| 1204 } | |
| 1205 | |
| 1206 client->timeout = timeout; | |
| 1207 | |
| 1208 #if 0 | |
| 1209 PKIX_CHECK(pkix_HttpCertStore_FindSocketConnection | |
| 1210 (timeout, | |
| 1211 "variation.red.iplanet.com", /* (char *)client->host, */ | |
| 1212 2001, /* client->portnum, */ | |
| 1213 &status, | |
| 1214 &socket, | |
| 1215 plContext), | |
| 1216 PKIX_HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED); | |
| 1217 #else | |
| 1218 PKIX_CHECK(pkix_HttpCertStore_FindSocketConnection | |
| 1219 (timeout, | |
| 1220 (char *)client->host, | |
| 1221 client->portnum, | |
| 1222 &status, | |
| 1223 &socket, | |
| 1224 plContext), | |
| 1225 PKIX_HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED); | |
| 1226 #endif | |
| 1227 | |
| 1228 client->socket = socket; | |
| 1229 | |
| 1230 PKIX_CHECK(pkix_pl_Socket_GetCallbackList | |
| 1231 (socket, &callbackList, plContext), | |
| 1232 PKIX_SOCKETGETCALLBACKLISTFAILED); | |
| 1233 | |
| 1234 client->callbackList = (void *)callbackList; | |
| 1235 | |
| 1236 PKIX_CHECK(pkix_pl_Socket_GetPRFileDesc | |
| 1237 (socket, &fileDesc, plContext), | |
| 1238 PKIX_SOCKETGETPRFILEDESCFAILED); | |
| 1239 | |
| 1240 client->pollDesc.fd = fileDesc; | |
| 1241 client->pollDesc.in_flags = 0; | |
| 1242 client->pollDesc.out_flags = 0; | |
| 1243 | |
| 1244 client->send_http_data = NULL; | |
| 1245 client->send_http_data_len = 0; | |
| 1246 client->send_http_content_type = NULL; | |
| 1247 | |
| 1248 client->connectStatus = | |
| 1249 ((status == 0) ? HTTP_CONNECTED : HTTP_CONNECT_PENDING); | |
| 1250 | |
| 1251 /* Request object is the same object as Session object */ | |
| 1252 PKIX_INCREF(client); | |
| 1253 *pRequest = client; | |
| 1254 | |
| 1255 cleanup: | |
| 1256 | |
| 1257 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 1258 | |
| 1259 } | |
| 1260 | |
| 1261 PKIX_Error * | |
| 1262 pkix_pl_HttpDefaultClient_SetPostData( | |
| 1263 SEC_HTTP_REQUEST_SESSION request, | |
| 1264 const char *http_data, | |
| 1265 const PRUint32 http_data_len, | |
| 1266 const char *http_content_type, | |
| 1267 void *plContext) | |
| 1268 { | |
| 1269 PKIX_PL_HttpDefaultClient *client = NULL; | |
| 1270 | |
| 1271 PKIX_ENTER | |
| 1272 (HTTPDEFAULTCLIENT, | |
| 1273 "pkix_pl_HttpDefaultClient_SetPostData"); | |
| 1274 PKIX_NULLCHECK_ONE(request); | |
| 1275 | |
| 1276 PKIX_CHECK(pkix_CheckType | |
| 1277 ((PKIX_PL_Object *)request, | |
| 1278 PKIX_HTTPDEFAULTCLIENT_TYPE, | |
| 1279 plContext), | |
| 1280 PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); | |
| 1281 | |
| 1282 client = (PKIX_PL_HttpDefaultClient *)request; | |
| 1283 | |
| 1284 client->send_http_data = http_data; | |
| 1285 client->send_http_data_len = http_data_len; | |
| 1286 client->send_http_content_type = http_content_type; | |
| 1287 | |
| 1288 /* Caller is allowed to give NULL or empty string for content_type */ | |
| 1289 if ((client->send_http_content_type == NULL) || | |
| 1290 (*(client->send_http_content_type) == '\0')) { | |
| 1291 client->send_http_content_type = "application/ocsp-request"; | |
| 1292 } | |
| 1293 | |
| 1294 cleanup: | |
| 1295 | |
| 1296 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 1297 | |
| 1298 } | |
| 1299 | |
| 1300 PKIX_Error * | |
| 1301 pkix_pl_HttpDefaultClient_TrySendAndReceive( | |
| 1302 SEC_HTTP_REQUEST_SESSION request, | |
| 1303 PRUint16 *http_response_code, | |
| 1304 const char **http_response_content_type, | |
| 1305 const char **http_response_headers, | |
| 1306 const char **http_response_data, | |
| 1307 PRUint32 *http_response_data_len, | |
| 1308 PRPollDesc **pPollDesc, | |
| 1309 SECStatus *pSECReturn, | |
| 1310 void *plContext) | |
| 1311 { | |
| 1312 PKIX_PL_HttpDefaultClient *client = NULL; | |
| 1313 PKIX_UInt32 postLen = 0; | |
| 1314 PRPollDesc *pollDesc = NULL; | |
| 1315 char *sendbuf = NULL; | |
| 1316 char portstr[16]; | |
| 1317 | |
| 1318 PKIX_ENTER | |
| 1319 (HTTPDEFAULTCLIENT, | |
| 1320 "pkix_pl_HttpDefaultClient_TrySendAndReceive"); | |
| 1321 | |
| 1322 PKIX_NULLCHECK_ONE(request); | |
| 1323 | |
| 1324 PKIX_CHECK(pkix_CheckType | |
| 1325 ((PKIX_PL_Object *)request, | |
| 1326 PKIX_HTTPDEFAULTCLIENT_TYPE, | |
| 1327 plContext), | |
| 1328 PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); | |
| 1329 | |
| 1330 client = (PKIX_PL_HttpDefaultClient *)request; | |
| 1331 | |
| 1332 if (!pPollDesc && client->timeout == 0) { | |
| 1333 PKIX_ERROR_FATAL(PKIX_NULLARGUMENT); | |
| 1334 } | |
| 1335 | |
| 1336 if (pPollDesc) { | |
| 1337 pollDesc = *pPollDesc; | |
| 1338 } | |
| 1339 | |
| 1340 /* if not continuing from an earlier WOULDBLOCK return... */ | |
| 1341 if (pollDesc == NULL) { | |
| 1342 | |
| 1343 if (!((client->connectStatus == HTTP_CONNECTED) || | |
| 1344 (client->connectStatus == HTTP_CONNECT_PENDING))) { | |
| 1345 PKIX_ERROR(PKIX_HTTPCLIENTININVALIDSTATE); | |
| 1346 } | |
| 1347 | |
| 1348 /* Did caller provide a value for response length? */ | |
| 1349 if (http_response_data_len != NULL) { | |
| 1350 client->pRcv_http_data_len = http_response_data_len; | |
| 1351 client->maxResponseLen = *http_response_data_len; | |
| 1352 } | |
| 1353 | |
| 1354 client->rcv_http_response_code = http_response_code; | |
| 1355 client->rcv_http_content_type = http_response_content_type; | |
| 1356 client->rcv_http_headers = http_response_headers; | |
| 1357 client->rcv_http_data = http_response_data; | |
| 1358 | |
| 1359 /* prepare the message */ | |
| 1360 portstr[0] = '\0'; | |
| 1361 if (client->portnum != 80) { | |
| 1362 PR_snprintf(portstr, sizeof(portstr), ":%d", | |
| 1363 client->portnum); | |
| 1364 } | |
| 1365 | |
| 1366 if (client->send_http_method == HTTP_POST_METHOD) { | |
| 1367 sendbuf = PR_smprintf | |
| 1368 ("POST %s HTTP/1.0\r\nHost: %s%s\r\n" | |
| 1369 "Content-Type: %s\r\nContent-Length: %u\r\n\r\n", | |
| 1370 client->path, | |
| 1371 client->host, | |
| 1372 portstr, | |
| 1373 client->send_http_content_type, | |
| 1374 client->send_http_data_len); | |
| 1375 postLen = PORT_Strlen(sendbuf); | |
| 1376 | |
| 1377 client->POSTLen = postLen + client->send_http_data_len; | |
| 1378 | |
| 1379 /* allocate postBuffer big enough for header + data */ | |
| 1380 PKIX_CHECK(PKIX_PL_Malloc | |
| 1381 (client->POSTLen, | |
| 1382 (void **)&(client->POSTBuf), | |
| 1383 plContext), | |
| 1384 PKIX_MALLOCFAILED); | |
| 1385 | |
| 1386 /* copy header into postBuffer */ | |
| 1387 PORT_Memcpy(client->POSTBuf, sendbuf, postLen); | |
| 1388 | |
| 1389 /* append data after header */ | |
| 1390 PORT_Memcpy(&client->POSTBuf[postLen], | |
| 1391 client->send_http_data, | |
| 1392 client->send_http_data_len); | |
| 1393 | |
| 1394 /* PR_smprintf_free original header buffer */ | |
| 1395 PR_smprintf_free(sendbuf); | |
| 1396 sendbuf = NULL; | |
| 1397 | |
| 1398 } else if (client->send_http_method == HTTP_GET_METHOD) { | |
| 1399 client->GETBuf = PR_smprintf | |
| 1400 ("GET %s HTTP/1.0\r\nHost: %s%s\r\n\r\n", | |
| 1401 client->path, | |
| 1402 client->host, | |
| 1403 portstr); | |
| 1404 client->GETLen = PORT_Strlen(client->GETBuf); | |
| 1405 } | |
| 1406 | |
| 1407 } | |
| 1408 | |
| 1409 /* continue according to state */ | |
| 1410 PKIX_CHECK(pkix_pl_HttpDefaultClient_Dispatch(client, plContext), | |
| 1411 PKIX_HTTPDEFAULTCLIENTDISPATCHFAILED); | |
| 1412 | |
| 1413 switch (client->connectStatus) { | |
| 1414 case HTTP_CONNECT_PENDING: | |
| 1415 case HTTP_SEND_PENDING: | |
| 1416 case HTTP_RECV_HDR_PENDING: | |
| 1417 case HTTP_RECV_BODY_PENDING: | |
| 1418 pollDesc = &(client->pollDesc); | |
| 1419 *pSECReturn = SECWouldBlock; | |
| 1420 break; | |
| 1421 case HTTP_ERROR: | |
| 1422 /* Did caller provide a pointer for length? */ | |
| 1423 if (client->pRcv_http_data_len != NULL) { | |
| 1424 /* Was error "response too big?" */ | |
| 1425 if (client->rcv_http_data_len != | |
| 1426 HTTP_UNKNOWN_CONTENT_LENGTH && | |
| 1427 client->maxResponseLen >= | |
| 1428 client->rcv_http_data_len) { | |
| 1429 /* Yes, report needed space */ | |
| 1430 *(client->pRcv_http_data_len) = | |
| 1431 client->rcv_http_data_len; | |
| 1432 } else { | |
| 1433 /* No, report problem other than size */ | |
| 1434 *(client->pRcv_http_data_len) = 0; | |
| 1435 } | |
| 1436 } | |
| 1437 | |
| 1438 pollDesc = NULL; | |
| 1439 *pSECReturn = SECFailure; | |
| 1440 break; | |
| 1441 case HTTP_COMPLETE: | |
| 1442 *(client->rcv_http_response_code) = | |
| 1443 client->responseCode; | |
| 1444 if (client->pRcv_http_data_len != NULL) { | |
| 1445 *http_response_data_len = | |
| 1446 client->rcv_http_data_len; | |
| 1447 } | |
| 1448 if (client->rcv_http_data != NULL) { | |
| 1449 *(client->rcv_http_data) = client->rcvBuf; | |
| 1450 } | |
| 1451 pollDesc = NULL; | |
| 1452 *pSECReturn = SECSuccess; | |
| 1453 break; | |
| 1454 case HTTP_NOT_CONNECTED: | |
| 1455 case HTTP_CONNECTED: | |
| 1456 case HTTP_RECV_HDR: | |
| 1457 case HTTP_RECV_BODY: | |
| 1458 default: | |
| 1459 pollDesc = NULL; | |
| 1460 *pSECReturn = SECFailure; | |
| 1461 PKIX_ERROR(PKIX_HTTPCLIENTININVALIDSTATE); | |
| 1462 break; | |
| 1463 } | |
| 1464 | |
| 1465 if (pPollDesc) { | |
| 1466 *pPollDesc = pollDesc; | |
| 1467 } | |
| 1468 | |
| 1469 cleanup: | |
| 1470 if (sendbuf) { | |
| 1471 PR_smprintf_free(sendbuf); | |
| 1472 } | |
| 1473 | |
| 1474 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 1475 | |
| 1476 } | |
| 1477 | |
| 1478 PKIX_Error * | |
| 1479 pkix_pl_HttpDefaultClient_Cancel( | |
| 1480 SEC_HTTP_REQUEST_SESSION request, | |
| 1481 void *plContext) | |
| 1482 { | |
| 1483 PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Cancel"); | |
| 1484 PKIX_NULLCHECK_ONE(request); | |
| 1485 | |
| 1486 PKIX_CHECK(pkix_CheckType | |
| 1487 ((PKIX_PL_Object *)request, | |
| 1488 PKIX_HTTPDEFAULTCLIENT_TYPE, | |
| 1489 plContext), | |
| 1490 PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); | |
| 1491 | |
| 1492 /* XXX Not implemented */ | |
| 1493 | |
| 1494 cleanup: | |
| 1495 | |
| 1496 PKIX_RETURN(HTTPDEFAULTCLIENT); | |
| 1497 | |
| 1498 } | |
| 1499 | |
| 1500 SECStatus | |
| 1501 pkix_pl_HttpDefaultClient_CreateSessionFcn( | |
| 1502 const char *host, | |
| 1503 PRUint16 portnum, | |
| 1504 SEC_HTTP_SERVER_SESSION *pSession) | |
| 1505 { | |
| 1506 PKIX_Error *err = pkix_pl_HttpDefaultClient_CreateSession | |
| 1507 (host, portnum, pSession, plContext); | |
| 1508 | |
| 1509 if (err) { | |
| 1510 PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); | |
| 1511 return SECFailure; | |
| 1512 } | |
| 1513 return SECSuccess; | |
| 1514 } | |
| 1515 | |
| 1516 SECStatus | |
| 1517 pkix_pl_HttpDefaultClient_KeepAliveSessionFcn( | |
| 1518 SEC_HTTP_SERVER_SESSION session, | |
| 1519 PRPollDesc **pPollDesc) | |
| 1520 { | |
| 1521 PKIX_Error *err = pkix_pl_HttpDefaultClient_KeepAliveSession | |
| 1522 (session, pPollDesc, plContext); | |
| 1523 | |
| 1524 if (err) { | |
| 1525 PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); | |
| 1526 return SECFailure; | |
| 1527 } | |
| 1528 return SECSuccess; | |
| 1529 } | |
| 1530 | |
| 1531 SECStatus | |
| 1532 pkix_pl_HttpDefaultClient_FreeSessionFcn( | |
| 1533 SEC_HTTP_SERVER_SESSION session) | |
| 1534 { | |
| 1535 PKIX_Error *err = | |
| 1536 PKIX_PL_Object_DecRef((PKIX_PL_Object *)(session), plContext); | |
| 1537 | |
| 1538 if (err) { | |
| 1539 PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); | |
| 1540 return SECFailure; | |
| 1541 } | |
| 1542 return SECSuccess; | |
| 1543 } | |
| 1544 | |
| 1545 SECStatus | |
| 1546 pkix_pl_HttpDefaultClient_RequestCreateFcn( | |
| 1547 SEC_HTTP_SERVER_SESSION session, | |
| 1548 const char *http_protocol_variant, /* usually "http" */ | |
| 1549 const char *path_and_query_string, | |
| 1550 const char *http_request_method, | |
| 1551 const PRIntervalTime timeout, | |
| 1552 SEC_HTTP_REQUEST_SESSION *pRequest) | |
| 1553 { | |
| 1554 PKIX_Error *err = pkix_pl_HttpDefaultClient_RequestCreate | |
| 1555 (session, | |
| 1556 http_protocol_variant, | |
| 1557 path_and_query_string, | |
| 1558 http_request_method, | |
| 1559 timeout, | |
| 1560 pRequest, | |
| 1561 plContext); | |
| 1562 | |
| 1563 if (err) { | |
| 1564 PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); | |
| 1565 return SECFailure; | |
| 1566 } | |
| 1567 return SECSuccess; | |
| 1568 } | |
| 1569 | |
| 1570 SECStatus | |
| 1571 pkix_pl_HttpDefaultClient_SetPostDataFcn( | |
| 1572 SEC_HTTP_REQUEST_SESSION request, | |
| 1573 const char *http_data, | |
| 1574 const PRUint32 http_data_len, | |
| 1575 const char *http_content_type) | |
| 1576 { | |
| 1577 PKIX_Error *err = | |
| 1578 pkix_pl_HttpDefaultClient_SetPostData(request, http_data, | |
| 1579 http_data_len, | |
| 1580 http_content_type, | |
| 1581 plContext); | |
| 1582 if (err) { | |
| 1583 PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); | |
| 1584 return SECFailure; | |
| 1585 } | |
| 1586 return SECSuccess; | |
| 1587 } | |
| 1588 | |
| 1589 SECStatus | |
| 1590 pkix_pl_HttpDefaultClient_AddHeaderFcn( | |
| 1591 SEC_HTTP_REQUEST_SESSION request, | |
| 1592 const char *http_header_name, | |
| 1593 const char *http_header_value) | |
| 1594 { | |
| 1595 /* Not supported */ | |
| 1596 return SECFailure; | |
| 1597 } | |
| 1598 | |
| 1599 SECStatus | |
| 1600 pkix_pl_HttpDefaultClient_TrySendAndReceiveFcn( | |
| 1601 SEC_HTTP_REQUEST_SESSION request, | |
| 1602 PRPollDesc **pPollDesc, | |
| 1603 PRUint16 *http_response_code, | |
| 1604 const char **http_response_content_type, | |
| 1605 const char **http_response_headers, | |
| 1606 const char **http_response_data, | |
| 1607 PRUint32 *http_response_data_len) | |
| 1608 { | |
| 1609 SECStatus rv = SECFailure; | |
| 1610 | |
| 1611 PKIX_Error *err = pkix_pl_HttpDefaultClient_TrySendAndReceive | |
| 1612 (request, | |
| 1613 http_response_code, | |
| 1614 http_response_content_type, | |
| 1615 http_response_headers, | |
| 1616 http_response_data, | |
| 1617 http_response_data_len, | |
| 1618 pPollDesc, | |
| 1619 &rv, | |
| 1620 plContext); | |
| 1621 | |
| 1622 if (err) { | |
| 1623 PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); | |
| 1624 return rv; | |
| 1625 } | |
| 1626 return SECSuccess; | |
| 1627 } | |
| 1628 | |
| 1629 SECStatus | |
| 1630 pkix_pl_HttpDefaultClient_CancelFcn( | |
| 1631 SEC_HTTP_REQUEST_SESSION request) | |
| 1632 { | |
| 1633 PKIX_Error *err = pkix_pl_HttpDefaultClient_Cancel(request, plContext); | |
| 1634 | |
| 1635 if (err) { | |
| 1636 PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); | |
| 1637 return SECFailure; | |
| 1638 } | |
| 1639 return SECSuccess; | |
| 1640 } | |
| 1641 | |
| 1642 SECStatus | |
| 1643 pkix_pl_HttpDefaultClient_FreeFcn( | |
| 1644 SEC_HTTP_REQUEST_SESSION request) | |
| 1645 { | |
| 1646 PKIX_Error *err = | |
| 1647 PKIX_PL_Object_DecRef((PKIX_PL_Object *)(request), plContext); | |
| 1648 | |
| 1649 if (err) { | |
| 1650 PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); | |
| 1651 return SECFailure; | |
| 1652 } | |
| 1653 return SECSuccess; | |
| 1654 } | |
| OLD | NEW |