static int NonBlockingSSL_Accept(SSL* ssl) { #ifndef CYASSL_CALLBACKS int ret = SSL_accept(ssl); #else int ret = CyaSSL_accept_ex(ssl, srvHandShakeCB, srvTimeoutCB, srvTo); #endif int error = SSL_get_error(ssl, 0); SOCKET_T sockfd = (SOCKET_T)CyaSSL_get_fd(ssl); int select_ret; while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)) { int currTimeout = 1; if (error == SSL_ERROR_WANT_READ) { /* printf("... server would read block\n"); */ } else { /* printf("... server would write block\n"); */ } #ifdef CYASSL_DTLS currTimeout = CyaSSL_dtls_get_current_timeout(ssl); #endif select_ret = tcp_select(sockfd, currTimeout); if ((select_ret == TEST_RECV_READY) || (select_ret == TEST_ERROR_READY)) { #ifndef CYASSL_CALLBACKS ret = SSL_accept(ssl); #else ret = CyaSSL_accept_ex(ssl, srvHandShakeCB, srvTimeoutCB, srvTo); #endif error = SSL_get_error(ssl, 0); } else if (select_ret == TEST_TIMEOUT && !CyaSSL_dtls(ssl)) { error = SSL_ERROR_WANT_READ; } #ifdef CYASSL_DTLS else if (select_ret == TEST_TIMEOUT && CyaSSL_dtls(ssl) && CyaSSL_dtls_got_timeout(ssl) >= 0) { error = SSL_ERROR_WANT_READ; } #endif else { error = SSL_FATAL_ERROR; } } return ret; }
static void NonBlockingSSL_Connect(CYASSL* ssl) { #ifndef CYASSL_CALLBACKS int ret = CyaSSL_connect(ssl); #else int ret = CyaSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeout); #endif int error = CyaSSL_get_error(ssl, 0); SOCKET_T sockfd = (SOCKET_T)CyaSSL_get_fd(ssl); int select_ret; while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)) { int currTimeout = 1; if (error == SSL_ERROR_WANT_READ) printf("... client would read block\n"); else printf("... client would write block\n"); #ifdef CYASSL_DTLS currTimeout = CyaSSL_dtls_get_current_timeout(ssl); #endif select_ret = tcp_select(sockfd, currTimeout); if ((select_ret == TEST_RECV_READY) || (select_ret == TEST_ERROR_READY)) { #ifndef CYASSL_CALLBACKS ret = CyaSSL_connect(ssl); #else ret = CyaSSL_connect_ex(ssl,handShakeCB,timeoutCB,timeout); #endif error = CyaSSL_get_error(ssl, 0); } else if (select_ret == TEST_TIMEOUT && !CyaSSL_dtls(ssl)) { error = SSL_ERROR_WANT_READ; } #ifdef CYASSL_DTLS else if (select_ret == TEST_TIMEOUT && CyaSSL_dtls(ssl) && CyaSSL_dtls_got_timeout(ssl) >= 0) { error = SSL_ERROR_WANT_READ; } #endif else { error = SSL_FATAL_ERROR; } } if (ret != SSL_SUCCESS) err_sys("SSL_connect failed"); }
static void NonBlockingSSL_Accept(SSL* ssl) { #ifndef CYASSL_CALLBACKS int ret = SSL_accept(ssl); #else int ret = CyaSSL_accept_ex(ssl, srvHandShakeCB, srvTimeoutCB, srvTo); #endif int error = SSL_get_error(ssl, 0); SOCKET_T sockfd = (SOCKET_T)CyaSSL_get_fd(ssl); int select_ret; while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)) { if (error == SSL_ERROR_WANT_READ) printf("... server would read block\n"); else printf("... server would write block\n"); if (CyaSSL_dtls(ssl)) select_ret = tcp_select(sockfd, CyaSSL_dtls_get_current_timeout(ssl)); else select_ret = tcp_select(sockfd, 1); if ((select_ret == TEST_RECV_READY) || (select_ret == TEST_ERROR_READY)) { #ifndef CYASSL_CALLBACKS ret = SSL_accept(ssl); #else ret = CyaSSL_accept_ex(ssl, srvHandShakeCB, srvTimeoutCB, srvTo); #endif error = SSL_get_error(ssl, 0); } else if (select_ret == TEST_TIMEOUT && (!CyaSSL_dtls(ssl) || (CyaSSL_dtls_got_timeout(ssl) >= 0))) { error = SSL_ERROR_WANT_READ; } else { error = SSL_FATAL_ERROR; } } if (ret != SSL_SUCCESS) err_sys("SSL_accept failed"); }
/* * Pulled in from examples/server/server.c * Function to handle nonblocking. Loops until tcp_select notifies that it's * ready for action. */ int NonBlockingSSL(CYASSL* ssl) { int ret; int error; int select_ret; int sockfd = CyaSSL_get_fd(ssl); ret = CyaSSL_accept(ssl); error = CyaSSL_get_error(ssl, 0); while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)) { int currTimeout = 1; /* print out for user notification */ if (error == SSL_ERROR_WANT_READ) printf("... server would read block\n"); else printf("... server would write block\n"); select_ret = tcp_select(sockfd, currTimeout); /* if tcp_select signals ready try to accept otherwise continue loop*/ if ((select_ret == TEST_RECV_READY) || (select_ret == TEST_ERROR_READY)) { ret = CyaSSL_accept(ssl); error = CyaSSL_get_error(ssl, 0); } else if (select_ret == TEST_TIMEOUT) { error = SSL_ERROR_WANT_READ; } else { error = SSL_FATAL_ERROR; } } /* faliure to accept */ if (ret != SSL_SUCCESS) { printf("Fatal error : SSL_accept failed\n"); ret = SSL_FATAL_ERROR; } return ret; }
/* Connect using Nonblocking - DTLS version */ static void NonBlockingDTLS_Connect(CYASSL* ssl) { int ret = CyaSSL_connect(ssl); int error = CyaSSL_get_error(ssl, 0); int sockfd = (int)CyaSSL_get_fd(ssl); int select_ret; while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)) { int currTimeout = 1; if (error == SSL_ERROR_WANT_READ) printf("... client would read block\n"); else printf("... client would write block\n"); currTimeout = CyaSSL_dtls_get_current_timeout(ssl); select_ret = dtls_select(sockfd, currTimeout); if ( ( select_ret == TEST_RECV_READY) || (select_ret == TEST_ERROR_READY)) { ret = CyaSSL_connect(ssl); error = CyaSSL_get_error(ssl, 0); } else if (select_ret == TEST_TIMEOUT && !CyaSSL_dtls(ssl)) { error = 2; } else if (select_ret == TEST_TIMEOUT && CyaSSL_dtls(ssl) && CyaSSL_dtls_got_timeout(ssl) >= 0) { error = 2; } else{ error = SSL_FATAL_ERROR; } } if (ret != SSL_SUCCESS) { printf("SSL_connect failed with"); } }
/* * ======== tcpHandler ======== * Creates new Task to handle new TCP connections. */ Void tcpHandler(UArg arg0, UArg arg1) { int sockfd; int ret; struct sockaddr_in servAddr; Error_Block eb; bool flag = true; bool internal_flag = true; int nbytes; char *buffer; char msg[] = "Hello from TM4C1294XL Connected Launchpad"; CYASSL* ssl = (CYASSL *) arg0; fdOpenSession(TaskSelf()); CyaSSL_Init(); CYASSL_CTX* ctx = NULL; ctx = CyaSSL_CTX_new(CyaTLSv1_2_client_method()); if (ctx == 0) { System_printf("tcpHandler: CyaSSL_CTX_new error.\n"); exitApp(ctx); } if (CyaSSL_CTX_load_verify_buffer(ctx, ca_cert_der_2048, sizeof(ca_cert_der_2048) / sizeof(char), SSL_FILETYPE_ASN1) != SSL_SUCCESS) { System_printf("tcpHandler: Error loading ca_cert_der_2048" " please check the cyassl/certs_test.h file.\n"); exitApp(ctx); } if (CyaSSL_CTX_use_certificate_buffer(ctx, client_cert_der_2048, sizeof(client_cert_der_2048) / sizeof(char), SSL_FILETYPE_ASN1) != SSL_SUCCESS) { System_printf("tcpHandler: Error loading client_cert_der_2048," " please check the cyassl/certs_test.h file.\n"); exitApp(ctx); } if (CyaSSL_CTX_use_PrivateKey_buffer(ctx, client_key_der_2048, sizeof(client_key_der_2048) / sizeof(char), SSL_FILETYPE_ASN1) != SSL_SUCCESS) { System_printf("tcpHandler: Error loading client_key_der_2048," " please check the cyassl/certs_test.h file.\n"); exitApp(ctx); } /* Init the Error_Block */ Error_init(&eb); do { sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { System_printf("tcpHandler: socket failed\n"); Task_sleep(2000); continue; } memset((char *) &servAddr, 0, sizeof(servAddr)); servAddr.sin_family = AF_INET; servAddr.sin_port = htons(TCPPORT); inet_aton(IP_ADDR, &servAddr.sin_addr); ret = connect(sockfd, (struct sockaddr *) &servAddr, sizeof(servAddr)); if (ret < 0) { fdClose((SOCKET) sockfd); Task_sleep(2000); continue; } } while (ret != 0); if ((ssl = CyaSSL_new(ctx)) == NULL) { System_printf("tcpHandler: CyaSSL_new error.\n"); exitApp(ctx); } CyaSSL_set_fd(ssl, sockfd); ret = CyaSSL_connect(ssl); /* Delete "TOP_LINE" and "END_LINE" for debugging. */ /* TOP_LINE System_printf("looked for: %d.\n", SSL_SUCCESS); System_printf("return was: %d.\n", ret); int err; char err_buffer[80]; err = CyaSSL_get_error(ssl, 0); System_printf("CyaSSL error: %d\n", err); System_printf("CyaSSL error string: %s\n", CyaSSL_ERR_error_string(err, err_buffer)); END_LINE */ if (ret == SSL_SUCCESS) { sockfd = CyaSSL_get_fd(ssl); /* Get a buffer to receive incoming packets. Use the default heap. */ buffer = Memory_alloc(NULL, TCPPACKETSIZE, 0, &eb); if (buffer == NULL) { System_printf("tcpWorker: failed to alloc memory\n"); exitApp(ctx); } /* Say hello to the server */ while (flag) { if (CyaSSL_write(ssl, msg, strlen(msg)) != strlen(msg)) { ret = CyaSSL_get_error(ssl, 0); System_printf("Write error: %i.\n", ret); } while (internal_flag) { nbytes = CyaSSL_read(ssl, (char *) buffer, TCPPACKETSIZE); if (nbytes > 0) { internal_flag = false; } } /* success */ System_printf("Heard: \"%s\".\n", buffer); CyaSSL_free(ssl); fdClose((SOCKET) sockfd); flag = false; } /* Free the buffer back to the heap */ Memory_free(NULL, buffer, TCPPACKETSIZE); /* * Since deleteTerminatedTasks is set in the cfg file, * the Task will be deleted when the idle task runs. */ exitApp(ctx); } else { CyaSSL_free(ssl); fdClose((SOCKET) sockfd); System_printf("CyaSSL_connect failed.\n"); fdCloseSession(TaskSelf()); exitApp(ctx); } }
OSStatus SocketReadHTTPSBody( mico_ssl_t ssl, HTTPHeader_t *inHeader ) { OSStatus err = kParamErr; ssize_t readResult; int selectResult; fd_set readSet; size_t lastChunkLen, chunckheaderLen; char *nextPackagePtr; struct timeval_t t; size_t readLength; uint32_t pos = 0; t.tv_sec = 5; t.tv_usec = 0; int inSock = CyaSSL_get_fd( ssl ); require( inHeader, exit ); err = kNotReadableErr; FD_ZERO( &readSet ); FD_SET( inSock, &readSet ); /* Chunked data without content length */ if( inHeader->chunkedData == true ){ do{ /* Find Chunk data length */ while ( findChunkedDataLength( inHeader->chunkedDataBufferPtr, inHeader->extraDataLen, &inHeader->extraDataPtr ,"%llu", &inHeader->contentLength ) == false){ require_action(inHeader->extraDataLen < inHeader->chunkedDataBufferLen, exit, err=kMalformedErr ); selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL ); require_action( selectResult >= 1, exit, err = kNotReadableErr ); readResult = ssl_recv( ssl, inHeader->chunkedDataBufferPtr + inHeader->extraDataLen, (size_t)( inHeader->chunkedDataBufferLen - inHeader->extraDataLen ) ); if( readResult > 0 ) inHeader->extraDataLen += readResult; else { err = kConnectionErr; goto exit; } } chunckheaderLen = inHeader->extraDataPtr - inHeader->chunkedDataBufferPtr; /* Check the last chunk */ if(inHeader->contentLength == 0){ while( findCRLF( inHeader->extraDataPtr, inHeader->extraDataLen - chunckheaderLen, &nextPackagePtr ) == false){ //find CRLF selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL ); require_action( selectResult >= 1, exit, err = kNotReadableErr ); readResult = ssl_recv( ssl, (uint8_t *)( inHeader->extraDataPtr + inHeader->extraDataLen - chunckheaderLen ), 256 - inHeader->extraDataLen ); //Assume chunk trailer length is less than 256 (256 is the min chunk buffer, maybe dangerous if( readResult > 0 ) inHeader->extraDataLen += readResult; else { err = kConnectionErr; goto exit; } (inHeader->onReceivedDataCallback)(inHeader, inHeader->extraDataLen - readResult, (uint8_t *)inHeader->extraDataPtr, readResult, inHeader->userContext); } err = kNoErr; goto exit; } else{ // Read chunk data /* Chunk package already exist, callback, move to buffer's head */ if( inHeader->extraDataLen >= inHeader->contentLength + chunckheaderLen + 2 ){ require_action( *(inHeader->extraDataPtr + inHeader->contentLength ) == '\r' && *(inHeader->extraDataPtr + inHeader->contentLength + 1 ) == '\n', exit, err = kMalformedErr); (inHeader->onReceivedDataCallback)(inHeader, pos, (uint8_t *)inHeader->extraDataPtr, inHeader->contentLength, inHeader->userContext); pos+=inHeader->contentLength; /* Move next chunk to chunked data buffer header point */ lastChunkLen = inHeader->extraDataPtr - inHeader->chunkedDataBufferPtr + inHeader->contentLength; if(inHeader->contentLength) lastChunkLen += 2; //Last chunck data has a CRLF tail memmove( inHeader->chunkedDataBufferPtr, inHeader->chunkedDataBufferPtr + lastChunkLen, inHeader->chunkedDataBufferLen - lastChunkLen ); inHeader->extraDataLen -= lastChunkLen; } /* Chunck exist without the last LF, generate callback abd recv LF */ /* Callback , read LF */ else if(inHeader->extraDataLen == inHeader->contentLength + chunckheaderLen +1){ //recv CR require_action( *(inHeader->chunkedDataBufferPtr + inHeader->extraDataLen - 1) == '\r' , exit, err = kMalformedErr); (inHeader->onReceivedDataCallback)(inHeader, pos, (uint8_t *)inHeader->extraDataPtr, inHeader->extraDataLen - chunckheaderLen-1, inHeader->userContext); pos+=inHeader->extraDataLen - chunckheaderLen-1; selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL ); require_action( selectResult >= 1, exit, err = kNotReadableErr ); readResult = ssl_recv( ssl, (uint8_t *)inHeader->extraDataPtr, 1); if( readResult > 0 ) {} else { err = kConnectionErr; goto exit; } require_action( *(inHeader->extraDataPtr) == '\n', exit, err = kMalformedErr); inHeader->extraDataLen = 0; } else{ /* Callback , read , callback , read CRLF */ (inHeader->onReceivedDataCallback)(inHeader, pos, (uint8_t *)inHeader->extraDataPtr, inHeader->extraDataLen - chunckheaderLen, inHeader->userContext); pos += inHeader->extraDataLen - chunckheaderLen; while ( inHeader->extraDataLen < inHeader->contentLength + chunckheaderLen ){ selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL ); require_action( selectResult >= 1, exit, err = kNotReadableErr ); if( inHeader->contentLength - (inHeader->extraDataLen - chunckheaderLen) > inHeader->chunkedDataBufferLen - chunckheaderLen) //Data needed is greater than valid buffer size readLength = inHeader->chunkedDataBufferLen - chunckheaderLen; else //Data needed is less than valid buffer size readLength = inHeader->contentLength - (inHeader->extraDataLen - chunckheaderLen) ; readResult = ssl_recv( ssl, (uint8_t *)inHeader->extraDataPtr, readLength); if( readResult > 0 ) inHeader->extraDataLen += readResult; else { err = kConnectionErr; goto exit; } (inHeader->onReceivedDataCallback)(inHeader, pos, (uint8_t *)inHeader->extraDataPtr, readResult, inHeader->userContext); pos += readResult; } selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL ); require_action( selectResult >= 1, exit, err = kNotReadableErr ); readResult = ssl_recv( ssl, (uint8_t *)inHeader->extraDataPtr, 2); if( readResult > 0 ) {} else { err = kConnectionErr; goto exit; } require_action( *(inHeader->extraDataPtr) == '\r' && *(inHeader->extraDataPtr+1 ) == '\n', exit, err = kMalformedErr); inHeader->extraDataLen = 0; } } }while(inHeader->contentLength != 0); } /* We has extra data but total length is not clear, store them to 1500 bytes buffer return when connection is disconnected by remote server */ // if( inHeader->dataEndedbyClose == true){ // if(inHeader->contentLength == 0) { //First read body, return using data received by SocketReadHTTPHeader // inHeader->contentLength = inHeader->extraDataLen; // }else{ // selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL ); // require_action( selectResult >= 1, exit, err = kNotReadableErr ); // readResult = read( inSock, // (uint8_t*)( inHeader->extraDataPtr ), // 1500 ); // if( readResult > 0 ) inHeader->contentLength = readResult; // else { err = kConnectionErr; goto exit; } // } // err = kNoErr; // goto exit; // } while ( inHeader->extraDataLen < inHeader->contentLength ) { selectResult = select( inSock + 1, &readSet, NULL, NULL, &t ); require_action( selectResult >= 1, exit, err = kNotReadableErr ); if(inHeader->isCallbackSupported == true){ /* We has extra data, and we give these data to application by onReceivedDataCallback function */ readLength = inHeader->contentLength - inHeader->extraDataLen > READ_LENGTH? READ_LENGTH:inHeader->contentLength - inHeader->extraDataLen; readResult = ssl_recv( ssl, (uint8_t*)( inHeader->extraDataPtr), readLength ); if( readResult > 0 ) inHeader->extraDataLen += readResult; else { err = kConnectionErr; goto exit; } (inHeader->onReceivedDataCallback)(inHeader, inHeader->extraDataLen - readResult, (uint8_t *)inHeader->extraDataPtr, readResult, inHeader->userContext); }else{ /* We has extra data and we has a predefined buffer to store the total extra data return when all data has received*/ readResult = ssl_recv( ssl, (uint8_t*)( inHeader->extraDataPtr + inHeader->extraDataLen ), ( inHeader->contentLength - inHeader->extraDataLen ) ); if( readResult > 0 ) inHeader->extraDataLen += readResult; else { err = kConnectionErr; goto exit; } } } err = kNoErr; exit: if(err != kNoErr) inHeader->len = 0; return err; }