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