/* The receive embedded callback * return : nb bytes read * -1 : other errors (unexpected) * -2 : WANT_READ * -3 : Connexion reset * -4 : interrupt * -5 : connexion close */ int EmbedReceive(char *buf, int sz, void *ctx) { int recvd; int err; int socket = *(int*)ctx; recvd = RECV_FUNCTION(socket, (char *)buf, sz, 0); if (recvd == -1) { err = LastError(); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) return -2; else if (err == SOCKET_ECONNRESET) return -3; else if (err == SOCKET_EINTR) return -4; else return -1; } else if (recvd == 0) return -5; return recvd; }
/* The receive embedded callback * return : nb bytes read, or error */ int EmbedReceive(char *buf, int sz, void *ctx) { int recvd; int err; int sd = *(int*)ctx; recvd = RECV_FUNCTION(sd, (char *)buf, sz, 0); if (recvd < 0) { err = LastError(); CYASSL_MSG("Embed Receive error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { CYASSL_MSG(" Would block"); return IO_ERR_WANT_READ; } else if (err == SOCKET_ECONNRESET) { CYASSL_MSG(" Connection reset"); return IO_ERR_CONN_RST; } else if (err == SOCKET_EINTR) { CYASSL_MSG(" Socket interrupted"); return IO_ERR_ISR; } else { CYASSL_MSG(" General error"); return IO_ERR_GENERAL; } } else if (recvd == 0) { CYASSL_MSG("Embed receive connection closed"); return IO_ERR_CONN_CLOSE; } return recvd; }
/* The receive embedded callback * return : nb bytes read, or error */ int EmbedReceive(CYASSL *ssl, char *buf, int sz, void *ctx) { int recvd; int err; int sd = *(int*)ctx; #ifdef CYASSL_DTLS { int dtls_timeout = CyaSSL_dtls_get_current_timeout(ssl); if (CyaSSL_dtls(ssl) && !CyaSSL_get_using_nonblock(ssl) && dtls_timeout != 0) { #ifdef USE_WINDOWS_API DWORD timeout = dtls_timeout * 1000; #else struct timeval timeout; XMEMSET(&timeout, 0, sizeof(timeout)); timeout.tv_sec = dtls_timeout; #endif if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) != 0) { CYASSL_MSG("setsockopt rcvtimeo failed"); } } } #endif recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags); recvd = TranslateReturnCode(recvd, sd); if (recvd < 0) { err = LastError(); CYASSL_MSG("Embed Receive error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { if (!CyaSSL_dtls(ssl) || CyaSSL_get_using_nonblock(ssl)) { CYASSL_MSG(" Would block"); return CYASSL_CBIO_ERR_WANT_READ; } else { CYASSL_MSG(" Socket timeout"); return CYASSL_CBIO_ERR_TIMEOUT; } } else if (err == SOCKET_ECONNRESET) { CYASSL_MSG(" Connection reset"); return CYASSL_CBIO_ERR_CONN_RST; } else if (err == SOCKET_EINTR) { CYASSL_MSG(" Socket interrupted"); return CYASSL_CBIO_ERR_ISR; } else if (err == SOCKET_ECONNREFUSED) { CYASSL_MSG(" Connection refused"); return CYASSL_CBIO_ERR_WANT_READ; } else if (err == SOCKET_ECONNABORTED) { CYASSL_MSG(" Connection aborted"); return CYASSL_CBIO_ERR_CONN_CLOSE; } else { CYASSL_MSG(" General error"); return CYASSL_CBIO_ERR_GENERAL; } } else if (recvd == 0) { CYASSL_MSG("Embed receive connection closed"); return CYASSL_CBIO_ERR_CONN_CLOSE; } return recvd; }
/* return: >0 OCSP Response Size * -1 error */ static int process_http_response(int sfd, byte** respBuf, byte* httpBuf, int httpBufSz) { int result; int len = 0; char *start, *end; byte *recvBuf = NULL; int recvBufSz = 0; enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type, phr_wait_end, phr_http_end } state = phr_init; start = end = NULL; do { if (end == NULL) { result = (int)RECV_FUNCTION(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); if (result > 0) { len += result; start = (char*)httpBuf; start[len] = 0; } else { WOLFSSL_MSG("process_http_response recv http from peer failed"); return -1; } } end = XSTRSTR(start, "\r\n"); if (end == NULL) { if (len != 0) XMEMMOVE(httpBuf, start, len); start = end = NULL; } else if (end == start) { if (state == phr_wait_end) { state = phr_http_end; len -= 2; start += 2; } else { WOLFSSL_MSG("process_http_response header ended early"); return -1; } } else { *end = 0; len -= (int)(end - start) + 2; /* adjust len to remove the first line including the /r/n */ if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { start += 9; if (XSTRNCASECMP(start, "200 OK", 6) != 0 || state != phr_init) { WOLFSSL_MSG("process_http_response not OK"); return -1; } state = phr_http_start; } else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { start += 13; while (*start == ' ' && *start != '\0') start++; if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) { WOLFSSL_MSG("process_http_response not ocsp-response"); return -1; } if (state == phr_http_start) state = phr_have_type; else if (state == phr_have_length) state = phr_wait_end; else { WOLFSSL_MSG("process_http_response type invalid state"); return -1; } } else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { start += 15; while (*start == ' ' && *start != '\0') start++; recvBufSz = atoi(start); if (state == phr_http_start) state = phr_have_length; else if (state == phr_have_type) state = phr_wait_end; else { WOLFSSL_MSG("process_http_response length invalid state"); return -1; } } start = end + 2; } } while (state != phr_http_end); recvBuf = (byte*)XMALLOC(recvBufSz, NULL, DYNAMIC_TYPE_OCSP); if (recvBuf == NULL) { WOLFSSL_MSG("process_http_response couldn't create response buffer"); return -1; } /* copy the remainder of the httpBuf into the respBuf */ if (len != 0) XMEMCPY(recvBuf, start, len); /* receive the OCSP response data */ do { result = (int)RECV_FUNCTION(sfd, (char*)recvBuf+len, recvBufSz-len, 0); if (result > 0) len += result; else { WOLFSSL_MSG("process_http_response recv ocsp from peer failed"); return -1; } } while (len != recvBufSz); *respBuf = recvBuf; return recvBufSz; }