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;
}
BOOL RTIP_SOCKETS_Driver::Initialize()
{
    NATIVE_PROFILE_PAL_NETWORK();
    IFACE_INFO info;

    memset(g_RTIP_SOCKETS_Driver.m_interfaces, 0, sizeof(g_RTIP_SOCKETS_Driver.m_interfaces));

    /* Initialize the network stack   */
    if (rtp_net_init() != 0)
    {
        DEBUG_HANDLE_SOCKET_ERROR("rtp_net_init", TRUE);
        return FALSE;
    }

#if defined(NETWORK_USE_LOOPBACK)
    // Bind and Open the loopback driver
    g_LOOPBACK_Driver.Bind();
    
    if (g_LOOPBACK_Driver.Open() == SOCK_SOCKET_ERROR)
    {
        DEBUG_HANDLE_SOCKET_ERROR("loopback init", FALSE);
    }
#endif        

    for(int i=0; i<g_NetworkConfig.NetworkInterfaceCount; i++)
    {
        int interfaceNumber;
        
        SOCK_NetworkConfiguration *pNetCfg = &g_NetworkConfig.NetworkInterfaces[i];

        Network_Interface_Bind(i);

        interfaceNumber = Network_Interface_Open(i);
        
        if (interfaceNumber == SOCK_SOCKET_ERROR)
        {
            DEBUG_HANDLE_SOCKET_ERROR("Network init", FALSE);
            debug_printf("SocketError: %d\n", xn_getlasterror());
            continue;
        }

        g_RTIP_SOCKETS_Driver.m_interfaces[i].m_interfaceNumber = interfaceNumber;

        
        UpdateAdapterConfiguration(i, SOCK_NETWORKCONFIGURATION_UPDATE_DHCP | SOCK_NETWORKCONFIGURATION_UPDATE_DNS, pNetCfg);

        // default debugger interface
        if(0 == i)
        {
            // add multicast addresses to the routing table
            UINT32 mcast1 = SOCK_htonl(SOCK_DISCOVERY_MULTICAST_IPADDR);
            UINT32 mcast2 = SOCK_htonl(SOCK_DISCOVERY_MULTICAST_IPADDR_SND);
            UINT32 mask   = SOCK_htonl(SOCK_MAKE_IP_ADDR(255,255,255,255));
            
            if(SOCK_SOCKET_ERROR == xn_rt_add((RTP_PFCUINT8)&mcast1, (RTP_PFUINT8)&mask, (RTP_PFUINT8)0, RT_USEIFACEMETRIC, interfaceNumber, RT_INF))
            {
                DEBUG_HANDLE_SOCKET_ERROR("Multicast xn_rt_add (recv)", FALSE);
            }
            if(SOCK_SOCKET_ERROR == xn_rt_add((RTP_PFCUINT8)&mcast2, (RTP_PFUINT8)&mask, (RTP_PFUINT8)0, RT_USEIFACEMETRIC, interfaceNumber, RT_INF))
            {
                DEBUG_HANDLE_SOCKET_ERROR("Multicast xn_rt_add (send)", FALSE);
            }

            /* JRT - TBD call xn_ip_set_option */
            default_mcast_iface = interfaceNumber;
            
            xn_interface_info(interfaceNumber, &info );

            debug_printf( "ip address from interface info: %d.%d.%d.%d\r\n", (UINT32)info.my_ip_address[0], 
                                                                             (UINT32)info.my_ip_address[1],                                                                 
                                                                             (UINT32)info.my_ip_address[2], 
                                                                             (UINT32)info.my_ip_address[3] );
            
            debug_printf( "mac addrress from interface info: %x.%x.%x.%x.%x.%x\r\n", (UINT32)info.my_ethernet_address[0], 
                                                                                     (UINT32)info.my_ethernet_address[1],                                                                 
                                                                                     (UINT32)info.my_ethernet_address[2], 
                                                                                     (UINT32)info.my_ethernet_address[3],                                                            
                                                                                     (UINT32)info.my_ethernet_address[4], 
                                                                                     (UINT32)info.my_ethernet_address[5] );
        }
    }
    
    return TRUE;
}