bool OTSocket::Send(const std::string & str_Reply)
{
	OT_ASSERT_MSG(NULL != m_pSocket, "m_pSocket == NULL in OTSocket::Send()");
	OT_ASSERT_MSG(NULL != m_pContext, "m_pContext == NULL in OTSocket::Send()");
	OT_ASSERT_MSG(str_Reply.size() > 0, "str_Reply.size() > 0");
	// -----------------------------------
	const long lLatencySendMilliSec	= OTLog::GetLatencySendMs();
	const long lLatencySendMicroSec	= lLatencySendMilliSec*1000; // Microsecond is 1000 times smaller than millisecond.
	
	// Convert the std::string (reply) into a ZMQ message
	zmq::message_t reply (str_Reply.length());
	memcpy((void *) reply.data(), str_Reply.c_str(), str_Reply.length());
	// -----------------------------------
	
	bool bSuccessSending	= false;
	
	if (OTLog::IsBlocking())
	{
		bSuccessSending = m_pSocket->send(reply); // Blocking.
	}
	else // not blocking
	{
		int		nSendTries	= OTLog::GetLatencySendNoTries();
		long	lDoubling	= lLatencySendMicroSec;		
		bool	bKeepTrying = true;
		
		while (bKeepTrying && (nSendTries > 0))
		{
			zmq::pollitem_t items [] = {
				{ (*m_pSocket), 0, ZMQ_POLLOUT,	0 }
			};
			
			const int nPoll = zmq::poll(&items[0], 1, lDoubling);	// ZMQ_POLLOUT, 1 item, timeout (microseconds in ZMQ 2.1; changes to milliseconds in 3.0)					
			lDoubling *= 2;
			
			if (items[0].revents & ZMQ_POLLOUT)
			{
				bSuccessSending = m_pSocket->send(reply, ZMQ_NOBLOCK); // <=========== SEND ===============
				OTLog::SleepMilliseconds( 1 );
				
				if (!bSuccessSending)
				{
					if (false == HandleSendingError())
						bKeepTrying = false;
				}
				else
					break; // (Success -- we're done in this loop.)
			}
			else if ((-1) == nPoll) // error.
			{
				if (false == HandlePollingError())
					bKeepTrying = false;
			}
			
			--nSendTries;
		}
	}
	
	return bSuccessSending;
}
bool OTSocket_ZMQ_4::Send(const OTASCIIArmor & ascEnvelope)
{
    if (!m_bInitialized) { OT_FAIL; }

    if (0 >= ascEnvelope.GetLength())  { OTLog::vError("%s: Error: %s is zero length!\n", __FUNCTION__, "ascEnvelope");	OT_FAIL; }
    m_ascLastMsgSent.Set(ascEnvelope); // In case we need to re-send.

    if (!m_HasContext) { OT_FAIL; }
    if (NULL == m_pzmq->context_zmq)  { OTLog::vError("%s: Error: %s must exist to Send!\n", __FUNCTION__, "m_pzmq->context_zmq");	OT_FAIL; }

    if (!m_bConnected && !m_bListening) return false;
    if (m_bConnected && m_bListening) return false;
    if (NULL == m_pzmq->socket_zmq) { OTLog::vError("%s: Error: %s must exist to Send!\n", __FUNCTION__, "m_pzmq->socket_zmq");	OT_FAIL; }


    // -----------------------------------	
    const int64_t lLatencySendMilliSec = m_lLatencySendMs;

    zmq::message_t zmq_message(ascEnvelope.GetLength());
    memcpy((void*)zmq_message.data(), ascEnvelope.Get(), ascEnvelope.GetLength());

    bool bSuccessSending = false;

    if (m_bIsBlocking)
    {
        try {
            bSuccessSending = m_pzmq->socket_zmq->send(zmq_message); // Blocking.
        }
        catch (std::exception& e) {
            OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__, e.what());
            OT_FAIL;
        }
    }
    else // not blocking
    {
        int32_t		nSendTries = m_nLatencySendNoTries;
        int64_t	lDoubling = lLatencySendMilliSec;
        bool	bKeepTrying = true;

        while (bKeepTrying && (nSendTries > 0))
        {
            zmq::pollitem_t items[] = {
                { (*m_pzmq->socket_zmq), 0, ZMQ_POLLOUT, 0 }
            };

            int nPoll = 0;
            try {
                nPoll = zmq::poll(&items[0], 1, static_cast<long>(lDoubling));	// ZMQ_POLLOUT, 1 item, timeout (milliseconds)	
            }
            catch (std::exception& e) {
                OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__, e.what());
                OT_FAIL;
            }

            lDoubling *= 2;

            if (items[0].revents & ZMQ_POLLOUT)
            {
                try {
                    bSuccessSending = m_pzmq->socket_zmq->send(zmq_message, ZMQ_NOBLOCK); // <=========== SEND ===============
                }
                catch (std::exception& e) {
                    OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__, e.what());
                    OT_FAIL;
                }

                OTLog::SleepMilliseconds(1);

                if (!bSuccessSending)
                {
                    if (false == HandleSendingError())
                        bKeepTrying = false;
                }
                else
                    break; // (Success -- we're done in this loop.)
            }
            else if ((-1) == nPoll) // error.
            {
                if (false == HandlePollingError())
                    bKeepTrying = false;
            }

            --nSendTries;
        }
    }
    /*
    Normally, we try to send...
    If the send fails, we wait X ms and then try again (Y times).

    BUT -- what if the failure was an errno==EAGAIN ?
    In that case, it's not a REAL failure, but rather, a "failure right now, try again in a sec."
    */
    // ***********************************

    if (bSuccessSending)
        OTLog::SleepMilliseconds(m_lLatencyDelayAfter > 0 ? m_lLatencyDelayAfter : 1);

    return bSuccessSending;
}
bool OTSocket_ZMQ_2::Receive(OTString & strServerReply)
{
    if (!m_bInitialized) { OT_FAIL; }
    if (!m_HasContext) { OT_FAIL; }
    if (NULL == m_pzmq->context_zmq)  { OTLog::vError("%s: Error: %s must exist to Receive!\n", __FUNCTION__, "m_pzmq->context_zmq");	OT_FAIL; }

    if (!m_bConnected && !m_bListening) return false;
    if (m_bConnected && m_bListening) return false;
    if (NULL == m_pzmq->socket_zmq) { OTLog::vError("%s: Error: %s must exist to Receive!\n", __FUNCTION__, "m_pzmq->socket_zmq");	OT_FAIL; }


    // -----------------------------------	
    const long lLatencyRecvMilliSec = m_lLatencyReceiveMs;
    const long lLatencyRecvMicroSec = lLatencyRecvMilliSec * 1000;

    // ***********************************
    //  Get the reply.
    zmq::message_t zmq_message;

    bool bSuccessReceiving = false;

    // If failure receiving, re-tries 2 times, with 4000 ms max delay between each (Doubling every time.)
    //
    if (m_bIsBlocking)
    {
        bSuccessReceiving = m_pzmq->socket_zmq->recv(&zmq_message); // Blocking.
    }
    else	// not blocking
    {
        long	lDoubling = lLatencyRecvMicroSec;
        int		nReceiveTries = m_nLatencyReceiveNoTries;
        bool	expect_reply = true;
        while (expect_reply)
        {
            //  Poll socket for a reply, with timeout
            zmq::pollitem_t items[] = { { *m_pzmq->socket_zmq, 0, ZMQ_POLLIN, 0 } };

            const int nPoll = zmq::poll(&items[0], 1, lDoubling);
            lDoubling *= 2;

            //  If we got a reply, process it
            if (items[0].revents & ZMQ_POLLIN)
            {
                bSuccessReceiving = m_pzmq->socket_zmq->recv(&zmq_message, ZMQ_NOBLOCK); // <=========== RECEIVE ===============
                OTLog::SleepMilliseconds(1);

                if (!bSuccessReceiving)
                {
                    if (false == HandleReceivingError())
                        expect_reply = false;
                }
                else
                    break; // (Success -- we're done in this loop.)				
            }
            else if (nReceiveTries == 0)
            {
                //OTLog::Error("OTSocket::Receive: no message.\n");
                expect_reply = false;
                break;
            }
            else if ((-1) == nPoll) // error.
            {
                if (false == HandlePollingError())
                    expect_reply = false;
            }

            --nReceiveTries;
        }
    }
    // ***********************************

    if (bSuccessReceiving && (zmq_message.size() > 0))
        strServerReply.MemSet(static_cast<const char*>(zmq_message.data()), static_cast<uint32_t> (zmq_message.size()));

    return (bSuccessReceiving && (zmq_message.size() > 0));
}
bool OTSocket::Receive(std::string & str_Message)
{
	OT_ASSERT_MSG(NULL != m_pContext, "m_pContext == NULL in OTSocket::Receive()");
	OT_ASSERT_MSG(NULL != m_pSocket, "m_pSocket == NULL in OTSocket::Receive()");
	// -----------------------------------	
	const long lLatencyRecvMilliSec	= OTLog::GetLatencyReceiveMs();
	const long lLatencyRecvMicroSec	= lLatencyRecvMilliSec*1000;
	
	// ***********************************
	//  Get the request.
	zmq::message_t request;
	
	bool bSuccessReceiving = false;
	
	// If failure receiving, re-tries 2 times, with 4000 ms max delay between each (Doubling every time.)
	//
	if (OTLog::IsBlocking())
	{
		bSuccessReceiving = m_pSocket->recv(&request); // Blocking.
	}
	else	// not blocking
	{
		long	lDoubling = lLatencyRecvMicroSec;
		int		nReceiveTries = OTLog::GetLatencyReceiveNoTries();
		bool	expect_request = true;
		while (expect_request) 
		{
			//  Poll socket for a request, with timeout
			zmq::pollitem_t items[] = { { *m_pSocket, 0, ZMQ_POLLIN, 0 } };
			
			const int nPoll = zmq::poll (&items[0], 1, lDoubling);
			lDoubling *= 2; // 100 ms, then 200 ms, then 400 ms == total of 700 ms per receive. (About 15 per 10 seconds.)
			
			//  If we got a request, process it
			if (items[0].revents & ZMQ_POLLIN) 
			{
				bSuccessReceiving = m_pSocket->recv(&request, ZMQ_NOBLOCK); // <=========== RECEIVE ===============
				OTLog::SleepMilliseconds( 1 );
				
				if (!bSuccessReceiving)
				{
					if (false == HandleReceivingError())
						expect_request = false;
				}
				else
					break; // (Success -- we're done in this loop.)				
			}
			else if (nReceiveTries == 0) 
			{
//				OTLog::Error("OTSocket::Receive: Tried to receive, based on polling data, but failed even after retries.\n");
				expect_request = false;
				break;
			}
			else if ((-1) == nPoll) // error.
			{
				if (false == HandlePollingError())
					expect_request = false;
			}
			
			--nReceiveTries;
		}
	}
	// ***********************************
	
	if (bSuccessReceiving && (request.size() > 0))
	{
		str_Message.reserve(request.size());
		str_Message.append(static_cast<const char *>(request.data()), request.size());	
	}
	
	return (bSuccessReceiving && (request.size() > 0));
}