HRESULT Library_spot_net_security_native_Microsoft_SPOT_Net_Security_SslNative::SecureConnect___STATIC__VOID__I4__STRING__OBJECT( CLR_RT_StackFrame& stack ) { NATIVE_PROFILE_CLR_NETWORK(); TINYCLR_HEADER(); CLR_INT32 sslContext = stack.Arg0().NumericByRef().s4; CLR_RT_HeapBlock* hb = stack.Arg1().DereferenceString(); CLR_RT_HeapBlock* socket = stack.Arg2().Dereference(); CLR_INT32 timeout_ms = -1; // wait forever CLR_RT_HeapBlock hbTimeout; int result; LPCSTR szName; 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); } FAULT_ON_NULL_ARG(hb); szName = hb->StringText(); hbTimeout.SetInteger( timeout_ms ); TINYCLR_CHECK_HRESULT(stack.SetupTimeout( hbTimeout, timeout )); while(true) { result = SSL_Connect( handle, szName, 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 )); if(result < 0) break; } else { break; } } stack.PopValue(); // Timeout TINYCLR_CHECK_HRESULT(ThrowOnError( stack, result )); TINYCLR_NOCLEANUP(); }
/* Read/write from/to server at the specified socket. * * ctx The SSL/TLS connection data. * sslConn The SSL connection. * returns EXIT_FAILURE on failure and EXIT_SUCCESS otherwise. */ static int SSLConn_ReadWrite(SSLConn_CTX* ctx, SSLConn* sslConn) { int ret = 0; int len; switch (sslConn->state) { case INIT: case CLOSE: break; /* Perform TLS handshake. */ case CONNECT: ret = SSL_Connect(sslConn->ssl, ctx->resume, sslConn->session, &ctx->connTime, &ctx->resumeTime); if (ret == 0) { sslConn->state = CLOSE; return EXIT_FAILURE; } if (ret == 1) { sslConn->state = WRITE; } break; case WRITE: len = ctx->replyLen; if (ctx->maxBytes > 0) { len = min(len, ctx->maxBytes - ctx->totalWriteBytes); } /* Don't write if we are done. */ if (len == 0) break; /* Write application data. */ ret = SSL_Write(sslConn->ssl, ctx->reply, len, &ctx->totalWriteBytes, &ctx->writeTime); if (ret == 0) { sslConn->state = CLOSE; return EXIT_FAILURE; } if (ret == 1) sslConn->state = READ_WAIT; break; case READ_WAIT: ret = TCP_Select(sslConn->sockfd, 0); if (ret != 1) break; sslConn->state = READ; case READ: len = ctx->bufferLen; if (ctx->maxBytes > 0) { len = min(len, ctx->maxBytes - ctx->totalReadBytes); } /* Don't read if we are done. */ if (len == 0) break; /* Read application data. */ ret = SSL_Read(sslConn->ssl, ctx->buffer, len, &ctx->totalReadBytes, &ctx->readTime); if (ret == 0) { sslConn->state = CLOSE; return EXIT_FAILURE; } if (ret == 1) { if (ctx->maxConnections > 0) sslConn->state = CLOSE; else sslConn->state = WRITE; } break; } sslConn->err = ret; return EXIT_SUCCESS; }