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();
}
HRESULT Library_spot_native_Microsoft_SPOT_Messaging_EndPoint::GetMessage___MicrosoftSPOTMessagingMessage__I4( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_MESSAGING();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*                   pThis;
    CLR_RT_HeapBlock_EndPoint*          ep;
    CLR_RT_HeapBlock_EndPoint::Message* msg = NULL;
    CLR_INT64*                          timeout;
    bool                                fRes;

    pThis = stack.This(); FAULT_ON_NULL(pThis);

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_EndPoint::ExtractInstance( pThis[ FIELD__m_handle ], ep ));

    TINYCLR_CHECK_HRESULT(stack.SetupTimeout( stack.Arg1(), timeout ));

    fRes = true;
    while(fRes)
    {
        msg = ep->FindMessage( CLR_Messaging_Commands::c_Messaging_Send, NULL );

        if(msg) break;

        TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_EndPoint, fRes ));
    }

    stack.PopValue();

    {
        CLR_RT_HeapBlock& top = stack.PushValueAndClear();

        if(msg)
        {
            CLR_RT_HeapBlock*          pMsg;
            CLR_RT_ReflectionDef_Index val; val.InitializeFromHash( msg->m_addr.m_from.m_type );

            TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( top, g_CLR_RT_WellKnownTypes.m_Message ));

            pMsg = top.Dereference();
            pMsg[ Library_spot_native_Microsoft_SPOT_Messaging_Message::FIELD__m_source   ].SetObjectReference( pThis                   );
            pMsg[ Library_spot_native_Microsoft_SPOT_Messaging_Message::FIELD__m_selector ].SetReflection     ( val                     );
            pMsg[ Library_spot_native_Microsoft_SPOT_Messaging_Message::FIELD__m_id       ].SetInteger        ( msg->m_addr.m_from.m_id );
            pMsg[ Library_spot_native_Microsoft_SPOT_Messaging_Message::FIELD__m_seq      ].SetInteger        ( msg->m_addr.m_seq       );

            TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( pMsg[ Library_spot_native_Microsoft_SPOT_Messaging_Message::FIELD__m_payload ], msg->m_length, g_CLR_RT_WellKnownTypes.m_UInt8 ));

            memcpy( pMsg[ Library_spot_native_Microsoft_SPOT_Messaging_Message::FIELD__m_payload ].DereferenceArray()->GetFirstElement(), msg->m_data, msg->m_length );

            msg->Unlink(); CLR_RT_Memory::Release( msg );
        }
    }

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::poll___STATIC__BOOLEAN__OBJECT__I4__I4( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock* socket = stack.Arg0().Dereference();
    CLR_INT32 handle;
    CLR_INT32 mode       = stack.Arg1().NumericByRef().s4;    
    CLR_INT32 timeout_us = stack.Arg2().NumericByRef().s4;
    
    CLR_RT_HeapBlock hbTimeout;
    CLR_INT32 timeout_ms;

    CLR_INT32 res = 0;
    bool fRes     = true;

    CLR_INT64* timeout;

    FAULT_ON_NULL(socket);
    handle = socket[ 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 == DISPOSED_HANDLE)
    {
        ThrowError( stack, CLR_E_OBJECT_DISPOSED );
        TINYCLR_SET_AND_LEAVE (CLR_E_PROCESS_EXCEPTION);
    }


    if(timeout_us < 0) timeout_ms = -1;
    else               timeout_ms = timeout_us / 1000;

    hbTimeout.SetInteger( timeout_ms );

    TINYCLR_CHECK_HRESULT(stack.SetupTimeout( hbTimeout, timeout ));

    while(fRes)
    {
        res = Helper__SelectSocket( handle, mode );

        if(res != 0) break;

        TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes ));
    }

    stack.PopValue(); //timer

    TINYCLR_CHECK_HRESULT(ThrowOnError( stack, res ));

    stack.SetResult_Boolean( res == 1 );   

    TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_AppDomain::Unload___STATIC__VOID__SystemAppDomain( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    CLR_RT_AppDomain* appDomainSav;
    CLR_RT_AppDomain* appDomain;
    CLR_RT_HeapBlock  hbTimeout;
    CLR_INT64*        timeout;
    bool              fRes;
    
    TINYCLR_CHECK_HRESULT(GetAppDomain( stack.ThisRef(), appDomain, appDomainSav, false ));

    hbTimeout.SetInteger( 5 * 1000 );
    
    if(stack.m_customState == 0)
    {        
        //Attempt to unload the AppDomain only once
        TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.UnloadAppDomain( appDomain, stack.m_owningThread ));            
    }

    TINYCLR_CHECK_HRESULT(stack.SetupTimeout( hbTimeout, timeout ));

    fRes = true;
    while(fRes)
    {
        //Check to make sure this AppDomain is the one that caused the event to fire
        if(appDomain->m_state == CLR_RT_AppDomain::AppDomainState_Unloaded) break;

        _ASSERTE(CLR_EE_IS(UnloadingAppDomain));

        TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_AppDomain, fRes ));
    }

    if(!fRes) TINYCLR_SET_AND_LEAVE(CLR_E_TIMEOUT);

    appDomain->DestroyInstance();

    stack.PopValue();
    
    TINYCLR_CLEANUP();

    g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav );    

    TINYCLR_CLEANUP_END();
}
HRESULT Library_spot_hardware_serial_native_System_IO_Ports_SerialPort::Read___I4__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_HARDWARE();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_Array* readBuffer;
    CLR_RT_HeapBlock*       pThis;
    CLR_RT_HeapBlock*       config;
    CLR_UINT8*              ptr;
    CLR_INT32               offset;
    CLR_INT32               count;
    CLR_INT32               totLength;
    CLR_INT32               totRead;
    CLR_RT_HeapBlock*       timeout;
    CLR_INT64*              timeoutTicks;
    CLR_INT32               port;
    bool                    fRes;

    pThis = stack.This();  FAULT_ON_NULL(pThis);

    // check if the object was disposed
    if(pThis[ FIELD__m_fDisposed ].NumericByRef().s1 != 0) 
    {
        TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);
    }
    
    config = pThis[ FIELD__m_config ].Dereference(); FAULT_ON_NULL(config);

    readBuffer = stack.Arg1().DereferenceArray();  FAULT_ON_NULL(readBuffer);
    offset     = stack.Arg2().NumericByRef().s4;
    count      = stack.Arg3().NumericByRef().s4;
    totLength  = readBuffer->m_numOfElements;
    timeout    = &config[ Library_spot_hardware_serial_native_System_IO_Ports_SerialPort__Configuration::FIELD__ReadTimeout ];
    port       = config[ Library_spot_hardware_serial_native_System_IO_Ports_SerialPort__Configuration::FIELD__PortIndex ].NumericByRef().s4;

    //
    // Bound checking.
    //
    if(offset < 0 || offset > totLength)
    {
        TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
    }

    if(count == -1)
    {
        count = totLength - offset;
    }
    else
    {
        if(count < 0 || (offset+count) > totLength)
        {
            TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
        }
    }

    TINYCLR_CHECK_HRESULT(stack.SetupTimeout( *timeout, timeoutTicks ));

    //
    // Push "totRead" onto the eval stack.
    //
    if(stack.m_customState == 1)
    {
        stack.PushValueI4( 0 );
        
        stack.m_customState = 2;
    }

    //--//

    totRead = stack.m_evalStack[ 1 ].NumericByRef().s4;

    ptr    = readBuffer->GetFirstElement();
    ptr   += offset + totRead;
    count -= totRead;

    fRes = true;

    while(fRes && count > 0)
    {
        int read = ::USART_Read( port, (char*)ptr, count );

        if(read == 0)
        {
            stack.m_evalStack[ 1 ].NumericByRef().s4 = totRead;

            TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeoutTicks, CLR_RT_ExecutionEngine::c_Event_SerialPort, fRes ));
        }
        else if(read < 0)
        {
            TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
        }
        else
        {
            ptr     += read;
            totRead += read;
            count   -= read;
        }
    }

    stack.PopValue();       // totRead
    stack.PopValue();       // Timeout

    stack.SetResult_I4( totRead );

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_net_security_native_Microsoft_SPOT_Net_Security_SslNative::ReadWriteHelper( CLR_RT_StackFrame& stack, bool isWrite )
{
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       socket     = stack.Arg0().Dereference();
    CLR_RT_HeapBlock_Array* arrData    = stack.Arg1().DereferenceArray(); 
    CLR_INT32               offset     = stack.Arg2().NumericByRef().s4;
    CLR_INT32               count      = stack.Arg3().NumericByRef().s4;
    CLR_INT32               timeout_ms = stack.Arg4().NumericByRef().s4;
    CLR_UINT8*              buffer;
    CLR_RT_HeapBlock        hbTimeout;

    CLR_INT32  totReadWrite;
    bool       fRes = true;
    CLR_INT64 *timeout;
    int        result = 0;
    CLR_INT32 handle;

    if(count == 0) 
    {
        stack.SetResult_I4( 0 );
        TINYCLR_SET_AND_LEAVE(S_OK);
    }

    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(arrData);

    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;

    buffer = arrData->GetElement( offset + totReadWrite );
    count -= totReadWrite;

    if((offset + count + totReadWrite) > (int)arrData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_INDEX_OUT_OF_RANGE);    

    while(count > 0)
    {
        // first make sure we have data to read or ability to write
        while(fRes)
        {
            if(!isWrite)
            {
                // check SSL_DataAvailable() in case SSL has already read and buffered socket data
                result = SSL_DataAvailable(handle);

                if((result > 0) || ((result < 0) && (SOCK_getlasterror() != SOCK_EWOULDBLOCK)))
                {
                    break;
                }
            }

            result = Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::Helper__SelectSocket( handle, isWrite ? 1 : 0 );

            if((result > 0) || ((result < 0) && (SOCK_getlasterror() != SOCK_EWOULDBLOCK)))
            {
                break;
            }

            // 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 ));

            // timeout expired 
            if(!fRes)
            {
                result = 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 == result)
        {
            break;
        }

        if(isWrite)
        {
            result = SSL_Write( handle, (const char*)buffer, count );
        }
        else
        {
            result = SSL_Read( handle, (char*)buffer, count );

            if(result == SSL_RESULT__WOULD_BLOCK)
            {
                continue;
            }
        }

        // ThrowOnError expects anything other than 0 to be a failure - so return 0 if we don't have an error
        if(result <= 0)
        {
            break;
        }

        buffer       += result;
        totReadWrite += result;
        count        -= result;


        // read is non-blocking if we have any data
        if(!isWrite && (totReadWrite > 0))
        {
            break;
        }

        stack.m_evalStack[ 1 ].NumericByRef().s4 = totReadWrite;        
    }

    stack.PopValue();       // totReadWrite
    stack.PopValue();       // Timeout

    if(result < 0)
    {
        TINYCLR_CHECK_HRESULT(ThrowOnError( stack, result ));
    }

    stack.SetResult_I4( totReadWrite );
    
    TINYCLR_NOCLEANUP();
    
}
HRESULT Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::getaddrinfo___STATIC__VOID__STRING__BYREF_STRING__BYREF_SZARRAY_SZARRAY_U1( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    LPCSTR szName = stack.Arg0().RecoverString();
    struct SOCK_addrinfo hints;
    struct SOCK_addrinfo* addr = NULL;
    struct SOCK_addrinfo* addrT;
    CLR_UINT32        cAddresses = 0;
    CLR_RT_HeapBlock* pAddress;
    CLR_INT32         timeout_ms = 30000;
    CLR_RT_HeapBlock  hbTimeout;
    CLR_INT32         ret;
    bool              fRes = true;
    CLR_INT64*        timeout;

    hbTimeout.SetInteger( timeout_ms );

    TINYCLR_CHECK_HRESULT(stack.SetupTimeout( hbTimeout, timeout ));

    do
    {
        memset( &hints, 0, sizeof(hints) );

        ret = SOCK_getaddrinfo( szName, NULL, &hints, &addr );

        if(ret == SOCK_SOCKET_ERROR)
        {
            if(SOCK_getlasterror() == SOCK_EWOULDBLOCK)
            {
                // 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 ));
            }
            else
            {
                break;
            }
        }
        else
        {
            break;
        }
    }
    while(fRes);
    
    // timeout expired
    if(!fRes)
    {
        ret = SOCK_SOCKET_ERROR;
        
        ThrowError( stack, SOCK_ETIMEDOUT );
    
        TINYCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION );
    }

    // getaddrinfo returns a winsock error code rather than SOCK_SOCKET_ERROR, so pass this on to the exception handling
    if(ret != 0)
    {
        ThrowError( stack, ret );
        TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION);
    }

    {
        CLR_RT_HeapBlock  hbCanonicalName;
        CLR_RT_HeapBlock  hbAddresses;
        
        hbCanonicalName.SetObjectReference( NULL );
        CLR_RT_ProtectFromGC gc( hbCanonicalName );

        hbAddresses.SetObjectReference( NULL );
        CLR_RT_ProtectFromGC gc2( hbAddresses );

        for(int pass = 0; pass < 2; pass++)
        {                                    
            cAddresses = 0;

            for(addrT = addr; addrT != NULL; addrT = addrT->ai_next)
            {
                if(pass == 1)
                {
                    if(addrT->ai_canonname && addrT->ai_canonname[ 0 ])
                    {
                        //allocate return string
                        TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbCanonicalName, addrT->ai_canonname ));
                        TINYCLR_CHECK_HRESULT(hbCanonicalName.StoreToReference( stack.Arg1(), 0 ));
                    }

                    //allocate address and store into array
                    pAddress = (CLR_RT_HeapBlock*)hbAddresses.DereferenceArray()->GetElement( cAddresses );

                    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( *pAddress, (CLR_UINT32)addrT->ai_addrlen, g_CLR_RT_WellKnownTypes.m_UInt8 ));

                    //copy address.
                    memcpy( pAddress->DereferenceArray()->GetFirstElement(), addrT->ai_addr, addrT->ai_addrlen );
                }
                                
                cAddresses++;
            }
                            
            if(pass == 0)
            {
                //allocate array of byte arrays
                CLR_RT_ReflectionDef_Index idx;

                idx.m_kind               = REFLECTION_TYPE;
                idx.m_levels             = 2;
                idx.m_data.m_type.m_data = g_CLR_RT_WellKnownTypes.m_UInt8.m_data;

                TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( hbAddresses, cAddresses, idx ));

                TINYCLR_CHECK_HRESULT(hbAddresses.StoreToReference( stack.Arg2(), 0 ));                
            }
        }    
    }

    stack.PopValue();       // Timeout
    
    TINYCLR_CLEANUP();

    if( addr ) SOCK_freeaddrinfo( addr );

    TINYCLR_CLEANUP_END();
}
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();
}
HRESULT Library_spot_native_Microsoft_SPOT_Messaging_EndPoint::Check___BOOLEAN__mscorlibSystemType__U4__I4( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_MESSAGING();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*                   pThis;
    CLR_RT_HeapBlock_EndPoint::Message* msg;
    CLR_RT_HeapBlock_EndPoint::Port     port;
    CLR_RT_HeapBlock_EndPoint*          ep;
    CLR_INT64*                          timeout;
    bool                                fRes;
    CLR_UINT32                          seq;

    pThis = stack.This(); FAULT_ON_NULL(pThis);

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_EndPoint::ExtractInstance( pThis[ FIELD__m_handle ], ep ));

    if(CLR_RT_ReflectionDef_Index::Convert( stack.Arg1(), port.m_type ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE);
    port.m_id = stack.Arg2().NumericByRefConst().u4;

    TINYCLR_CHECK_HRESULT(stack.SetupTimeout( stack.Arg3(), timeout ));

    //
    // Send message.
    //
    if(stack.m_customState == 1)
    {
        CLR_Messaging_Commands::Messaging_Query rpc;

        rpc.m_addr.m_from = ep->m_addr;
        rpc.m_addr.m_seq  = ep->m_seq++;
        rpc.m_addr.m_to   = port;

        //
        // Push sequence number onto the eval stack to wait for reply.
        //
        stack.PushValueI4( rpc.m_addr.m_seq );
        
        CLR_EE_MSG_EVENT_RPC( CLR_Messaging_Commands::c_Messaging_Query, sizeof(rpc), &rpc, WP_Flags::c_NonCritical );
        
        stack.m_customState = 2;
    }

    //
    // Get seq# from stack
    //
    seq = stack.m_evalStack[ 1 ].NumericByRef().u4;

    fRes = true;
    msg  = NULL;

    while(fRes)
    {
        msg = ep->FindMessage( CLR_Messaging_Commands::c_Messaging_Query, &seq );

        if(msg) break;

        TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_EndPoint, fRes ));
    }

    stack.PopValue();       //seq
    stack.PopValue();       //Timeout

    fRes = false;

    if(msg)
    {
        fRes = (msg->m_found != 0);

        msg->Unlink(); CLR_RT_Memory::Release( msg );
    }

    stack.SetResult_Boolean( fRes );

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_native_Microsoft_SPOT_Messaging_EndPoint::SendMessageRaw___SZARRAY_U1__mscorlibSystemType__U4__I4__SZARRAY_U1( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_MESSAGING();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*                           pThis;
    CLR_Messaging_Commands::Messaging_Send*     rpc;
    CLR_RT_HeapBlock_EndPoint::Message*         msg;
    CLR_RT_HeapBlock_EndPoint::Port             port;
    CLR_RT_HeapBlock_EndPoint*                  ep;
    CLR_INT64*                                  timeout;
    CLR_RT_HeapBlock_Array*                     pData;
    CLR_UINT32                                  len;
    bool                                        fRes;
    CLR_UINT32                                  seq;

    pThis = stack.This(); FAULT_ON_NULL(pThis);

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_EndPoint::ExtractInstance( pThis[ FIELD__m_handle ], ep ));

    if(CLR_RT_ReflectionDef_Index::Convert( stack.Arg1(), port.m_type ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE);
    port.m_id = stack.Arg2().NumericByRefConst().u4;

    TINYCLR_CHECK_HRESULT(stack.SetupTimeout( stack.Arg3(), timeout ));

    pData = stack.Arg4().DereferenceArray(); FAULT_ON_NULL(pData);

    //Send message
    rpc = NULL;
    if(stack.m_customState == 1)
    {
        len = sizeof(CLR_RT_HeapBlock_EndPoint::Address) + pData->m_numOfElements;
        rpc = (CLR_Messaging_Commands::Messaging_Send*)CLR_RT_Memory::Allocate( len ); CHECK_ALLOCATION(rpc);

        rpc->m_addr.m_to   = port;
        rpc->m_addr.m_from = ep->m_addr;
        rpc->m_addr.m_seq  = ep->m_seq++;
        memcpy( rpc->m_data, pData->GetFirstElement(), pData->m_numOfElements );

        //Push sequence number onto the eval stack to wait for reply
        stack.PushValueI4( rpc->m_addr.m_seq );
        
        CLR_EE_MSG_EVENT_RPC( CLR_Messaging_Commands::c_Messaging_Send, len, rpc, WP_Flags::c_NonCritical );
        
        stack.m_customState = 2;
    }

    //get seq# from stack
    seq = stack.m_evalStack[ 1 ].NumericByRef().u4;

    fRes = true;
    msg  = NULL;

    while(fRes)
    {
        msg = ep->FindMessage( CLR_Messaging_Commands::c_Messaging_Reply, &seq );

        if(msg) break;

        TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_EndPoint, fRes ));
    }

    stack.PopValue();       //seq
    stack.PopValue();       //Timeout

    {
        CLR_RT_HeapBlock& top = stack.PushValueAndClear();

        if(msg)
        {
            TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( top, msg->m_length, g_CLR_RT_WellKnownTypes.m_UInt8 ));

            memcpy( top.DereferenceArray()->GetFirstElement(), msg->m_data, msg->m_length );

            msg->Unlink(); CLR_RT_Memory::Release( msg );
        }
    }

    TINYCLR_NOCLEANUP();
}