INT32 SNTPClient::Connect() { SOCK_SOCKET timeSocket = SOCK_SOCKET_ERROR; INT32 sockErr = 0; UINT32 usedServer = 0; // look up outstdanding queries for this set of servers OutstandingQuery* query = FindOutstandingConnection(m_ipAddressPrimary, m_ipAddressAlternate); if(query != NULL) { // // signal failed queries // if(query->IsOld()) { query->Dispose(); query = NULL; } else { // // resume old connection // timeSocket = query->GetSocket(); } } if(timeSocket == SOCK_SOCKET_ERROR) { // // new connection // timeSocket = SOCK_socket(SOCK_AF_INET, SOCK_SOCK_DGRAM, SOCK_IPPROTO_UDP); if(timeSocket == SOCK_SOCKET_ERROR) { sockErr = SOCK_getlasterror(); return (sockErr == 0 ? HAL_TIMESERVICE_ERROR : sockErr); } SOCK_sockaddr addr; SOCK_sockaddr_in* dst = (SOCK_sockaddr_in*)&addr; memset(dst, 0, sizeof(SOCK_sockaddr_in)); dst->sin_family = SOCK_AF_INET; dst->sin_port = SOCK_htons(123); dst->sin_addr.S_un.S_addr = SOCK_htonl(m_ipAddressPrimary); usedServer = m_ipAddressPrimary; if(SOCK_connect(timeSocket, &addr, sizeof(addr)) == SOCK_SOCKET_ERROR && SOCK_getlasterror() != SOCK_EWOULDBLOCK) { if(m_ipAddressAlternate != 0) { usedServer = m_ipAddressAlternate; dst->sin_addr.S_un.S_addr = SOCK_htonl(m_ipAddressAlternate); if(SOCK_connect(timeSocket, &addr, sizeof(addr)) == SOCK_SOCKET_ERROR && SOCK_getlasterror() != SOCK_EWOULDBLOCK) { sockErr = SOCK_getlasterror(); SOCK_close(timeSocket); return (sockErr == 0 ? HAL_TIMESERVICE_ERROR : sockErr); } } else { sockErr = SOCK_getlasterror(); SOCK_close(timeSocket); return (sockErr == 0 ? HAL_TIMESERVICE_ERROR : sockErr); } } Initialize(); int sent = SOCK_send(timeSocket, (char*)SNTPData, sizeof(SNTPData), 0); if(sent != sizeof(SNTPData)) { sockErr = SOCK_getlasterror(); SOCK_close(timeSocket); return (sockErr == 0 ? HAL_TIMESERVICE_ERROR : sockErr); } } // retry 10 times every time we stop by INT32 retry = 10; INT32 bytesToRead = c_SNTPDataLength; char* buf = (char*)SNTPData; while(retry-- > 0) { int read = SOCK_recv(timeSocket, buf, bytesToRead, 0); if(read < 0 && (sockErr = SOCK_getlasterror()) != SOCK_EWOULDBLOCK) { SOCK_close(timeSocket); return (sockErr == 0 ? HAL_TIMESERVICE_ERROR : sockErr); } else if(read > 0) { bytesToRead -= read; if(bytesToRead <= 0) { break; } buf += read; // incase we start receiving data towards the end // of the retry limit. retry++; } } // if we could not finish reading, then cache and retry later // if we read a part of answer, then declare failure // in the future we could try and cope with this problem if(bytesToRead == c_SNTPDataLength) { // // if this is a new connection, get a slot // if(query == NULL) { query = GetQuery(usedServer, timeSocket); } return HAL_TIMESERVICE_WANT_READ_WRITE; } else if(bytesToRead > 0 && bytesToRead < c_SNTPDataLength) { if(query != NULL) query->Dispose(); return HAL_TIMESERVICE_WANT_READ_WRITE; } else { if(query != NULL) { query->Dispose(); query = NULL; } else { if( timeSocket != SOCK_SOCKET_ERROR ) { SOCK_close(timeSocket); timeSocket = SOCK_SOCKET_ERROR; } } } DestinationTimestamp = Time_GetUtcTime(); if( !IsResponseValid() ) { if(query != NULL) { query->Dispose(); query = NULL; } else { if( timeSocket != SOCK_SOCKET_ERROR ) { SOCK_close(timeSocket); timeSocket = SOCK_SOCKET_ERROR; } } return HAL_TIMESERVICE_ERROR; } return HAL_TIMESERVICE_SUCCESS; }
int ssl_read_internal(int socket, char* data, size_t size) { int rc = -1; MATRIXSSL_PDEBUG_ALL("size: %i\n", size); unsigned char *sslData; SSL* ssl = NULL; SSL_Conext* sslContext = g_SSL_Driver.GetSSLContextBySocketHandle(socket); if (sslContext != NULL && sslContext->SslContext != NULL) { ssl = (SSL*) sslContext->SslContext; } else { return SOCK_SOCKET_ERROR; } rc = handleBufferdData(sslContext, data, size); if (rc > 0 || rc == SOCK_SOCKET_ERROR) { //if data was buffered, return it and wait for next call to get new data from socket return rc; } int len = 0; len = matrixSslGetReadbuf(sslContext->SslContext, &sslData); int rec = SOCK_recv(sslContext->SocketHandle, (char*) sslData, len, 0); MATRIXSSL_PDEBUG_ALL("SOCK_recv: %i\n", rec); if (rec == 0) { return rec; } rc = matrixSslReceivedData(sslContext->SslContext, (int32) rec, &sslData, (uint32*) &len); PRINT_RETURN_VALUE(rc); if (rc < 0) { PRINT_UNEXPECTED_RETURN_VALUE(rc); return SOCK_SOCKET_ERROR; } MATRIXSSL_PDEBUG_ALL("matrixSslReceivedData: %i\n", len); if (!(rc == MATRIXSSL_APP_DATA || rc == MATRIXSSL_REQUEST_RECV || rc == MATRIXSSL_REQUEST_SEND || rc == MATRIXSSL_RECEIVED_ALERT)) { PRINT_UNEXPECTED_RETURN_VALUE(rc); return SOCK_SOCKET_ERROR; } if (rc == MATRIXSSL_RECEIVED_ALERT) { if (len == 2) { unsigned char alertLevel = sslData[0]; unsigned char alertDescription = sslData[1]; MATRIXSSL_PDEBUG( "Alert: Level %i, Description: %i\n", alertLevel, alertDescription); if (alertDescription == SSL_ALERT_CLOSE_NOTIFY) { return 0; } } return SOCK_SOCKET_ERROR; } else if (rc == MATRIXSSL_REQUEST_SEND) { int rc = handleRequestSend(sslContext); if (rc == MATRIXSSL_SUCCESS) { return 0; } return SOCK_SOCKET_ERROR; } else if (rc == MATRIXSSL_APP_DATA) { return handleAppData(size, len, data, sslData, sslContext); } else { return SSL_RESULT__WOULD_BLOCK; } PRINT_UNEXPECTED_RETURN_VALUE(rc); return 0; }
HRESULT Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::SendRecvHelper( CLR_RT_StackFrame& stack, bool fSend, bool fAddress ) { NATIVE_PROFILE_CLR_NETWORK(); TINYCLR_HEADER(); CLR_RT_HeapBlock* socket = stack.Arg0().Dereference(); CLR_INT32 handle; CLR_RT_HeapBlock_Array* arrData = stack.Arg1().DereferenceArray(); CLR_UINT32 offset = stack.Arg2().NumericByRef().u4; CLR_UINT32 count = stack.Arg3().NumericByRef().u4; CLR_INT32 flags = stack.Arg4().NumericByRef().s4; CLR_INT32 timeout_ms = stack.ArgN(5).NumericByRef().s4; CLR_RT_HeapBlock hbTimeout; CLR_INT64* timeout; CLR_UINT8* buf; bool fRes = true; CLR_INT32 totReadWrite; CLR_INT32 ret = 0; FAULT_ON_NULL(socket); handle = socket[ FIELD__m_Handle ].NumericByRef().s4; FAULT_ON_NULL(arrData); if(offset + count > arrData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_INDEX_OUT_OF_RANGE); /* 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 == 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 )); // // Push "totReadWrite" onto the eval stack. // if(stack.m_customState == 1) { stack.PushValueI4( 0 ); stack.m_customState = 2; } totReadWrite = stack.m_evalStack[ 1 ].NumericByRef().s4; buf = arrData->GetElement( offset + totReadWrite ); count -= totReadWrite; while(count > 0) { CLR_INT32 bytes = 0; // first make sure we have data to read or ability to write while(fRes) { ret = Helper__SelectSocket( handle, fSend ? 1 : 0 ); if(ret != 0) break; // non-blocking - allow other threads to run while we wait for handle activity TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes )); } // timeout expired if(!fRes) { ret = SOCK_SOCKET_ERROR; ThrowError( stack, SOCK_ETIMEDOUT ); TINYCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION ); } // socket is in the excepted state, so let's bail out if(SOCK_SOCKET_ERROR == ret) { break; } if(fAddress) { struct SOCK_sockaddr addr; CLR_UINT32 addrLen = sizeof(addr); CLR_RT_HeapBlock& blkAddr = stack.ArgN( 6 ); if(fSend) { TINYCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, blkAddr )); bytes = SOCK_sendto( handle, (const char*)buf, count, flags, &addr, addrLen ); } else { CLR_RT_HeapBlock* pBlkAddr = blkAddr.Dereference(); TINYCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, *pBlkAddr )); bytes = SOCK_recvfrom( handle, (char*)buf, count, flags, &addr, (int*)&addrLen ); if(bytes != SOCK_SOCKET_ERROR) { TINYCLR_CHECK_HRESULT(MarshalSockAddress( blkAddr, &addr, addrLen )); } } } else { if(fSend) { bytes = SOCK_send( handle, (const char*)buf, count, flags ); } else { bytes = SOCK_recv( handle, (char*)buf, count, flags ); } } // send/recv/sendto/recvfrom failed if(bytes == SOCK_SOCKET_ERROR) { CLR_INT32 err = SOCK_getlasterror(); if(err != SOCK_EWOULDBLOCK) { ret = SOCK_SOCKET_ERROR; break; } continue; } // zero recv bytes indicates the handle has been closed. else if(!fSend && (bytes == 0)) { break; } buf += bytes; totReadWrite += bytes; count -= bytes; stack.m_evalStack[ 1 ].NumericByRef().s4 = totReadWrite; // receive returns immediately after receiving bytes. if(!fSend && (totReadWrite > 0)) { break; } } stack.PopValue(); // totReadWrite stack.PopValue(); // Timeout TINYCLR_CHECK_HRESULT(ThrowOnError( stack, ret )); stack.SetResult_I4( totReadWrite ); TINYCLR_NOCLEANUP(); }
int ssl_connect_internal(int socket, const char* szTargetHost, int sslContextHandle) { static int status = MATRIXSSL_REQUEST_SEND; int ret = SOCK_SOCKET_ERROR; int nonblock = 0; int done = 0; SSL *ssl = NULL; SSL_Conext* sslContext = g_SSL_Driver.GetSSLContextBySslIndex( sslContextHandle); if (sslContext != NULL && sslContext->SslContext != NULL) { ssl = (SSL*) sslContext->SslContext; } else { MATRIXSSL_PERROR("Context not valid\n"); return SOCK_SOCKET_ERROR; } unsigned char *sslData; // WARNING - SSL_Connect is asynchronous and will be called multiple times for 1 connection, therefore // we only want to set the CA store on the first call (when sslData == NULL) // // The first certificate is the device's outbound certificate int rc = 0; int sent = 0; int len = matrixSslGetOutdata(ssl, &sslData); do { if (len > 0) //(status == MATRIXSSL_REQUEST_SEND ) { ret = SOCK_TRY_AGAIN; sent = SOCK_send(socket, (const char *) sslData, len, 0); //TODO check if sent rc = matrixSslSentData(ssl, sent); done = 1; if (rc == MATRIXSSL_SUCCESS) { status = MATRIXSSL_REQUEST_RECV; } } else //if(status == MATRIXSSL_REQUEST_RECV && done == 0) { int len = 1000; len = matrixSslGetReadbuf(ssl, &sslData); len = SOCK_recv(socket, (char*) sslData, len, 0); ret = SOCK_TRY_AGAIN; if (len > 0) { rc = matrixSslReceivedData(ssl, (int32) len, &sslData, (uint32*) &len); if (rc == MATRIXSSL_REQUEST_RECV) { status = MATRIXSSL_REQUEST_RECV; } if (rc == MATRIXSSL_REQUEST_SEND) { status = MATRIXSSL_REQUEST_SEND; ret = SOCK_TRY_AGAIN; } if (rc == MATRIXSSL_HANDSHAKE_COMPLETE) { ret = 0; } } } if (done == 0) { len = matrixSslGetOutdata(ssl, &sslData); } else { len = 0; } } while (len); g_SSL_Driver.AddSslSocketHandle(sslContextHandle, socket); return ret; }