HRESULT Library_spot_net_security_native_Microsoft_SPOT_Net_Security_SslNative::SecureAccept___STATIC__VOID__I4__OBJECT( CLR_RT_StackFrame& stack ) { NATIVE_PROFILE_CLR_NETWORK(); TINYCLR_HEADER(); CLR_INT32 sslContext = stack.Arg0().NumericByRef().s4; CLR_RT_HeapBlock* socket = stack.Arg1().Dereference(); CLR_INT32 timeout_ms = -1; // wait forever CLR_RT_HeapBlock hbTimeout; int result = 0; CLR_INT32 handle; bool fRes = true; CLR_INT64 *timeout; FAULT_ON_NULL(socket); handle = socket[ Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::FIELD__m_Handle ].NumericByRef().s4; /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see * if our handle has been shutdown before continuing. */ if (handle == Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::DISPOSED_HANDLE) { ThrowError(stack, CLR_E_OBJECT_DISPOSED); TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); } hbTimeout.SetInteger( timeout_ms ); TINYCLR_CHECK_HRESULT(stack.SetupTimeout( hbTimeout, timeout )); // first make sure we have data to read or ability to write while(true) { result = SSL_Accept( handle, sslContext ); if(result == SOCK_EWOULDBLOCK || result == SOCK_TRY_AGAIN) { // non-blocking - allow other threads to run while we wait for socket activity TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes )); } else { break; } } stack.PopValue(); // Timeout TINYCLR_CHECK_HRESULT(ThrowOnError( stack, result )); TINYCLR_NOCLEANUP(); }
/* Read/write from/to client at the specified socket. * * ctx The SSL/TLS connection data. * threadData The SSL connection data for a thread. * sslConn The SSL connection data object. * returns EXIT_FAILURE on failure and EXIT_SUCCESS otherwise. */ static int SSLConn_ReadWrite(SSLConn_CTX* ctx, ThreadData* threadData, SSLConn* sslConn) { int ret; int len; /* Perform TLS handshake if in accept state. */ switch (sslConn->state) { case ACCEPT: ret = SSL_Accept(sslConn->ssl, &ctx->acceptTime, &ctx->resumeTime); if (ret == 0) { printf("ERROR: Accept failed\n"); SSLConn_Close(ctx, threadData, sslConn); return EXIT_FAILURE; } if (ret == 1) sslConn->state = READ; break; case READ: { char buffer[NUM_READ_BYTES]; len = ctx->bufferLen; if (ctx->maxBytes > 0) { len = min(len, ctx->maxBytes - ctx->totalReadBytes); } if (len == 0) break; /* Read application data. */ ret = SSL_Read(sslConn->ssl, buffer, len, &ctx->totalReadBytes, &ctx->readTime); if (ret == 0) { SSLConn_Close(ctx, threadData, sslConn); return EXIT_FAILURE; } } if (ret != 1) break; sslConn->state = WRITE; case WRITE: len = ctx->replyLen; if (ctx->maxBytes > 0) { len = min(len, ctx->maxBytes - ctx->totalWriteBytes); } if (len == 0) break; /* Write application data. */ ret = SSL_Write(sslConn->ssl, reply, len, &ctx->totalWriteBytes, &ctx->writeTime); if (ret == 0) { printf("ERROR: Write failed\n"); SSLConn_Close(ctx, threadData, sslConn); return EXIT_FAILURE; } if (ret == 1) sslConn->state = READ; break; case CLOSED: break; } return EXIT_SUCCESS; }