Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Socket_ZMQ4.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * zmq4.cpp
4  * OTSocket with zmq4
5  */
6 
7 /************************************************************
8  -----BEGIN PGP SIGNED MESSAGE-----
9  Hash: SHA1
10 
11  * OPEN TRANSACTIONS
12  *
13  * Financial Cryptography and Digital Cash
14  * Library, Protocol, API, Server, CLI, GUI
15  *
16  * -- Anonymous Numbered Accounts.
17  * -- Untraceable Digital Cash.
18  * -- Triple-Signed Receipts.
19  * -- Cheques, Vouchers, Transfers, Inboxes.
20  * -- Basket Currencies, Markets, Payment Plans.
21  * -- Signed, XML, Ricardian-style Contracts.
22  * -- Scripted smart contracts.
23  *
24  * Copyright (C) 2010-2013 by "Fellow Traveler" (A pseudonym)
25  *
26  * EMAIL:
28  *
29  * BITCOIN: 1NtTPVVjDsUfDWybS4BwvHpG2pdS9RnYyQ
30  *
31  * KEY FINGERPRINT (PGP Key in license file):
32  * 9DD5 90EB 9292 4B48 0484 7910 0308 00ED F951 BB8E
33  *
34  * OFFICIAL PROJECT WIKI(s):
35  * https://github.com/FellowTraveler/Moneychanger
36  * https://github.com/FellowTraveler/Open-Transactions/wiki
37  *
38  * WEBSITE:
39  * http://www.OpenTransactions.org/
40  *
41  * Components and licensing:
42  * -- Moneychanger..A Java client GUI.....LICENSE:.....GPLv3
43  * -- otlib.........A class library.......LICENSE:...LAGPLv3
44  * -- otapi.........A client API..........LICENSE:...LAGPLv3
45  * -- opentxs/ot....Command-line client...LICENSE:...LAGPLv3
46  * -- otserver......Server Application....LICENSE:....AGPLv3
47  * Github.com/FellowTraveler/Open-Transactions/wiki/Components
48  *
49  * All of the above OT components were designed and written by
50  * Fellow Traveler, with the exception of Moneychanger, which
51  * was contracted out to Vicky C ([email protected]).
52  * The open-source community has since actively contributed.
53  *
54  * -----------------------------------------------------
55  *
56  * LICENSE:
57  * This program is free software: you can redistribute it
58  * and/or modify it under the terms of the GNU Affero
59  * General Public License as published by the Free Software
60  * Foundation, either version 3 of the License, or (at your
61  * option) any later version.
62  *
63  * ADDITIONAL PERMISSION under the GNU Affero GPL version 3
64  * section 7: (This paragraph applies only to the LAGPLv3
65  * components listed above.) If you modify this Program, or
66  * any covered work, by linking or combining it with other
67  * code, such other code is not for that reason alone subject
68  * to any of the requirements of the GNU Affero GPL version 3.
69  * (==> This means if you are only using the OT API, then you
70  * don't have to open-source your code--only your changes to
71  * Open-Transactions itself must be open source. Similar to
72  * LGPLv3, except it applies to software-as-a-service, not
73  * just to distributing binaries.)
74  *
75  * Extra WAIVER for OpenSSL, Lucre, and all other libraries
76  * used by Open Transactions: This program is released under
77  * the AGPL with the additional exemption that compiling,
78  * linking, and/or using OpenSSL is allowed. The same is true
79  * for any other open source libraries included in this
80  * project: complete waiver from the AGPL is hereby granted to
81  * compile, link, and/or use them with Open-Transactions,
82  * according to their own terms, as long as the rest of the
83  * Open-Transactions terms remain respected, with regard to
84  * the Open-Transactions code itself.
85  *
86  * Lucre License:
87  * This code is also "dual-license", meaning that Ben Lau-
88  * rie's license must also be included and respected, since
89  * the code for Lucre is also included with Open Transactions.
90  * See Open-Transactions/src/otlib/lucre/LUCRE_LICENSE.txt
91  * The Laurie requirements are light, but if there is any
92  * problem with his license, simply remove the Lucre code.
93  * Although there are no other blind token algorithms in Open
94  * Transactions (yet. credlib is coming), the other functions
95  * will continue to operate.
96  * See Lucre on Github: https://github.com/benlaurie/lucre
97  * -----------------------------------------------------
98  * You should have received a copy of the GNU Affero General
99  * Public License along with this program. If not, see:
100  * http://www.gnu.org/licenses/
101  *
102  * If you would like to use this software outside of the free
103  * software license, please contact FellowTraveler.
104  * (Unfortunately many will run anonymously and untraceably,
105  * so who could really stop them?)
106  *
107  * DISCLAIMER:
108  * This program is distributed in the hope that it will be
109  * useful, but WITHOUT ANY WARRANTY; without even the implied
110  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
111  * PURPOSE. See the GNU Affero General Public License for
112  * more details.
113 
114  -----BEGIN PGP SIGNATURE-----
115  Version: GnuPG v1.4.9 (Darwin)
116 
117  iQIcBAEBAgAGBQJRSsfJAAoJEAMIAO35UbuOQT8P/RJbka8etf7wbxdHQNAY+2cC
118  vDf8J3X8VI+pwMqv6wgTVy17venMZJa4I4ikXD/MRyWV1XbTG0mBXk/7AZk7Rexk
119  KTvL/U1kWiez6+8XXLye+k2JNM6v7eej8xMrqEcO0ZArh/DsLoIn1y8p8qjBI7+m
120  aE7lhstDiD0z8mwRRLKFLN2IH5rAFaZZUvj5ERJaoYUKdn4c+RcQVei2YOl4T0FU
121  LWND3YLoH8naqJXkaOKEN4UfJINCwxhe5Ke9wyfLWLUO7NamRkWD2T7CJ0xocnD1
122  sjAzlVGNgaFDRflfIF4QhBx1Ddl6wwhJfw+d08bjqblSq8aXDkmFA7HeunSFKkdn
123  oIEOEgyj+veuOMRJC5pnBJ9vV+7qRdDKQWaCKotynt4sWJDGQ9kWGWm74SsNaduN
124  TPMyr9kNmGsfR69Q2Zq/FLcLX/j8ESxU+HYUB4vaARw2xEOu2xwDDv6jt0j3Vqsg
125  x7rWv4S/Eh18FDNDkVRChiNoOIilLYLL6c38uMf1pnItBuxP3uhgY6COm59kVaRh
126  nyGTYCDYD2TK+fI9o89F1297uDCwEJ62U0Q7iTDp5QuXCoxkPfv8/kX6lS6T3y9G
127  M9mqIoLbIQ1EDntFv7/t6fUTS2+46uCrdZWbQ5RjYXdrzjij02nDmJAm2BngnZvd
128  kamH0Y/n11lCvo1oQxM+
129  =uSzz
130  -----END PGP SIGNATURE-----
131  **************************************************************/
132 
133 #include "../core/stdafx.hpp"
134 #include "Socket_ZMQ4.hpp"
135 #include "../core/OTLog.hpp"
136 
137 #include <cppzmq/zmq.hpp>
138 
139 namespace opentxs
140 {
141 
143 {
144 public:
145  ZMQ4();
146  ~ZMQ4();
147 
148  zmq::context_t* context_zmq;
149  zmq::socket_t* socket_zmq;
150 };
151 
153  : context_zmq(nullptr)
154  , socket_zmq(nullptr)
155 {
156 }
157 
159 {
160  delete socket_zmq;
161  delete context_zmq;
162 }
163 
165  : m_pzmq(new ZMQ4())
166 {
167 }
168 
170 {
171  CloseSocket();
172  delete (m_pzmq);
173 }
174 
175 bool OTSocket_ZMQ_4::CloseSocket(const bool bNewContext /*= false*/)
176 {
177  if (!m_bInitialized) return false;
178  if (!m_HasContext && !bNewContext) return false;
179 
180  if (nullptr != m_pzmq->socket_zmq) zmq_close(m_pzmq->socket_zmq);
181  if (nullptr != m_pzmq->socket_zmq) delete m_pzmq->socket_zmq;
182  m_pzmq->socket_zmq = nullptr;
183 
184  m_bConnected = false;
185  m_bListening = false;
186 
187  return true;
188 }
189 
190 bool OTSocket_ZMQ_4::NewSocket(const bool bIsRequest)
191 {
192  if (!m_bInitialized) return false;
193  if (!m_HasContext) return false;
194 
195  if (!CloseSocket()) return false;
196 
197  try {
198  m_pzmq->socket_zmq = new zmq::socket_t(
199  *m_pzmq->context_zmq,
200  bIsRequest ? ZMQ_REQ : ZMQ_REP); // make a new socket
201  }
202  catch (std::exception& e) {
203  OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__, e.what());
204  OT_FAIL;
205  }
206 
207  if (nullptr == m_pzmq->socket_zmq) {
208  OTLog::vError("%s: Error: %s failed to be created!\n", __FUNCTION__,
209  "m_pzmq->socket_zmq");
210  OT_FAIL;
211  }
212 
213  const int linger = 0; // close immediately
214 
215  try {
216  m_pzmq->socket_zmq->setsockopt(ZMQ_LINGER, &linger, sizeof(linger));
217  }
218  catch (std::exception& e) {
219  OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__, e.what());
220  OT_FAIL;
221  }
222 
223  m_bConnected = false;
224  m_bListening = false;
225 
226  return true;
227 }
228 
230 {
231  if (!m_bInitialized) return false;
232 
233  m_HasContext = false;
234 
235  if (!CloseSocket(true)) return false;
236 
237  if (nullptr != m_pzmq->context_zmq) zmq_term(m_pzmq->context_zmq);
238  if (nullptr != m_pzmq->context_zmq) delete m_pzmq->context_zmq;
239  m_pzmq->context_zmq = nullptr;
240 
241  try {
242  m_pzmq->context_zmq = new zmq::context_t(
243  1, 31); // Threads, Max Sockets. (31 is a sane default).
244  }
245  catch (std::exception& e) {
246  OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__, e.what());
247  OT_FAIL;
248  }
249 
250  m_HasContext = true;
251  return true;
252 }
253 
254 bool OTSocket_ZMQ_4::RemakeSocket(const bool bNewContext /*= false*/)
255 {
256 
257  if (!m_bInitialized) return false;
258  if (!m_HasContext) return false;
259 
260  if (!m_bConnected || !m_bListening) return false;
261  if (m_bConnected && m_bListening) return false;
262 
263  bool bConnected = m_bConnected;
264  bool bListening = m_bListening;
265 
266  if (bNewContext) NewContext();
267 
268  if (bConnected) return Connect();
269  if (bListening) return Listen();
270 
271  return false;
272 }
273 
275 {
276  if (!m_bInitialized) {
277  OT_FAIL;
278  }
279  if (!m_HasContext) {
280  OT_FAIL;
281  }
282 
283  if (nullptr == m_pzmq->context_zmq) {
284  OTLog::vError("%s: Error: %s must exist to Listen!\n", __FUNCTION__,
285  "m_pzmq->context_zmq");
286  OT_FAIL;
287  }
288  if (true == m_bListening) {
289  OTLog::vError("%s: Error: Must not be Listening, to Connect!\n",
290  __FUNCTION__);
291  OT_FAIL;
292  }
293 
294  if (!m_strConnectPath.Exists()) {
295  OT_FAIL;
296  }
297 
298  if (!NewSocket(true)) return false; // NewSocket(true), Request Socket.
299 
300  try {
301  m_pzmq->socket_zmq->connect(m_strConnectPath.Get());
302  }
303  catch (std::exception& e) {
304  OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__, e.what());
305  OT_FAIL;
306  }
307 
308  m_bConnected = true;
309  return true;
310 }
311 
313 {
314  if (!m_bInitialized) {
315  OT_FAIL;
316  }
317  if (!m_HasContext) {
318  OT_FAIL;
319  }
320 
321  if (nullptr == m_pzmq->context_zmq) {
322  OTLog::vError("%s: Error: %s must exist to Listen!\n", __FUNCTION__,
323  "m_pzmq->context_zmq");
324  OT_FAIL;
325  }
326  if (true == m_bConnected) {
327  OTLog::vError("%s: Error: Must not be Connected, to Listen!\n",
328  __FUNCTION__);
329  OT_FAIL;
330  }
331 
332  if (!m_strBindingPath.Exists()) {
333  OT_FAIL;
334  }
335 
336  if (!NewSocket(false)) return false; // NewSocket(false), Responce Socket.
337 
338  try {
339  m_pzmq->socket_zmq->bind(m_strBindingPath.Get()); // since
340  // m_strBindingPath
341  // was checked and set
342  // above.
343  }
344  catch (std::exception& e) {
345  OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__, e.what());
346  OT_FAIL;
347  }
348 
349  m_bListening = true;
350  return true;
351 }
352 
353 bool OTSocket_ZMQ_4::Connect(const OTString& strConnectPath)
354 {
355  if (!strConnectPath.Exists()) {
356  OTLog::vError("%s: Error: %s dosn't exist!\n", __FUNCTION__,
357  "strConnectPath");
358  OT_FAIL;
359  }
360  if (5 > strConnectPath.GetLength()) {
361  OTLog::vError("%s: Error: %s is too short!\n", __FUNCTION__,
362  "strConnectPath");
363  OT_FAIL;
364  }
365 
366  m_strConnectPath = strConnectPath; // set the connection path.
367 
368  return (Connect());
369 }
370 
371 bool OTSocket_ZMQ_4::Listen(const OTString& strBindingPath)
372 {
373  if (!strBindingPath.Exists()) {
374  OTLog::vError("%s: Error: %s dosn't exist!\n", __FUNCTION__,
375  "strBindingPath");
376  OT_FAIL;
377  }
378  if (5 > strBindingPath.GetLength()) {
379  OTLog::vError("%s: Error: %s is too short!\n", __FUNCTION__,
380  "strBindingPath");
381  OT_FAIL;
382  }
383 
384  m_strBindingPath = strBindingPath;
385 
386  return (Listen());
387 }
388 
389 bool OTSocket_ZMQ_4::Send(const OTASCIIArmor& ascEnvelope)
390 {
391  if (!m_bInitialized) {
392  OT_FAIL;
393  }
394 
395  if (0 >= ascEnvelope.GetLength()) {
396  OTLog::vError("%s: Error: %s is zero length!\n", __FUNCTION__,
397  "ascEnvelope");
398  OT_FAIL;
399  }
400  m_ascLastMsgSent.Set(ascEnvelope); // In case we need to re-send.
401 
402  if (!m_HasContext) {
403  OT_FAIL;
404  }
405  if (nullptr == m_pzmq->context_zmq) {
406  OTLog::vError("%s: Error: %s must exist to Send!\n", __FUNCTION__,
407  "m_pzmq->context_zmq");
408  OT_FAIL;
409  }
410 
411  if (!m_bConnected && !m_bListening) return false;
412  if (m_bConnected && m_bListening) return false;
413  if (nullptr == m_pzmq->socket_zmq) {
414  OTLog::vError("%s: Error: %s must exist to Send!\n", __FUNCTION__,
415  "m_pzmq->socket_zmq");
416  OT_FAIL;
417  }
418 
419  // -----------------------------------
420  const int64_t lLatencySendMilliSec = m_lLatencySendMs;
421 
422  zmq::message_t zmq_message(ascEnvelope.GetLength());
423  memcpy((void*)zmq_message.data(), ascEnvelope.Get(),
424  ascEnvelope.GetLength());
425 
426  bool bSuccessSending = false;
427 
428  if (m_bIsBlocking) {
429  try {
430  bSuccessSending =
431  m_pzmq->socket_zmq->send(zmq_message); // Blocking.
432  }
433  catch (std::exception& e) {
434  OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__,
435  e.what());
436  OT_FAIL;
437  }
438  }
439  else // not blocking
440  {
441  int32_t nSendTries = m_nLatencySendNoTries;
442  int64_t lDoubling = lLatencySendMilliSec;
443  bool bKeepTrying = true;
444 
445  while (bKeepTrying && (nSendTries > 0)) {
446  zmq::pollitem_t items[] = {
447  {(*m_pzmq->socket_zmq), 0, ZMQ_POLLOUT, 0}};
448 
449  int nPoll = 0;
450  try {
451  nPoll =
452  zmq::poll(&items[0], 1,
453  static_cast<long>(lDoubling)); // ZMQ_POLLOUT, 1
454  // item, timeout
455  // (milliseconds)
456  }
457  catch (std::exception& e) {
458  OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__,
459  e.what());
460  OT_FAIL;
461  }
462 
463  lDoubling *= 2;
464 
465  if (items[0].revents & ZMQ_POLLOUT) {
466  try {
467  bSuccessSending = m_pzmq->socket_zmq->send(
468  zmq_message,
469  ZMQ_NOBLOCK); // <=========== SEND ===============
470  }
471  catch (std::exception& e) {
472  OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__,
473  e.what());
474  OT_FAIL;
475  }
476 
478 
479  if (!bSuccessSending) {
480  if (!HandleSendingError()) bKeepTrying = false;
481  }
482  else
483  break; // (Success -- we're done in this loop.)
484  }
485  else if ((-1) == nPoll) // error.
486  {
487  if (!HandlePollingError()) bKeepTrying = false;
488  }
489 
490  --nSendTries;
491  }
492  }
493  /*
494  Normally, we try to send...
495  If the send fails, we wait X ms and then try again (Y times).
496 
497  BUT -- what if the failure was an errno==EAGAIN ?
498  In that case, it's not a REAL failure, but rather, a "failure right now, try
499  again in a sec."
500  */
501 
502  if (bSuccessSending)
504  : 1);
505 
506  return bSuccessSending;
507 }
508 
509 bool OTSocket_ZMQ_4::Send(const OTASCIIArmor& ascEnvelope,
510  const OTString& strConnectPath)
511 {
512  const bool bNewPath = m_strConnectPath.Compare(strConnectPath);
513 
514  if (!bNewPath) Connect(strConnectPath);
515 
516  if (!m_bConnected) OT_FAIL;
517 
518  return Send(ascEnvelope);
519 }
520 
521 bool OTSocket_ZMQ_4::Receive(OTString& strServerReply)
522 {
523  if (!m_bInitialized) {
524  OT_FAIL;
525  }
526  if (!m_HasContext) {
527  OT_FAIL;
528  }
529  if (nullptr == m_pzmq->context_zmq) {
530  OTLog::vError("%s: Error: %s must exist to Receive!\n", __FUNCTION__,
531  "m_pzmq->context_zmq");
532  OT_FAIL;
533  }
534 
535  if (!m_bConnected && !m_bListening) return false;
536  if (m_bConnected && m_bListening) return false;
537  if (nullptr == m_pzmq->socket_zmq) {
538  OTLog::vError("%s: Error: %s must exist to Receive!\n", __FUNCTION__,
539  "m_pzmq->socket_zmq");
540  OT_FAIL;
541  }
542 
543  // -----------------------------------
544  const int64_t lLatencyRecvMilliSec = m_lLatencyReceiveMs;
545 
546  //  Get the reply.
547  zmq::message_t zmq_message;
548 
549  bool bSuccessReceiving = false;
550 
551  // If failure receiving, re-tries 2 times, with 4000 ms max delay between
552  // each (Doubling every time.)
553  //
554  if (m_bIsBlocking) {
555  try {
556  bSuccessReceiving =
557  m_pzmq->socket_zmq->recv(&zmq_message); // Blocking.
558  }
559  catch (std::exception& e) {
560  OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__,
561  e.what());
562  OT_FAIL;
563  }
564  }
565  else // not blocking
566  {
567  int64_t lDoubling = lLatencyRecvMilliSec;
568  int32_t nReceiveTries = m_nLatencyReceiveNoTries;
569  bool expect_reply = true;
570  while (expect_reply) {
571  // Poll socket for a reply, with timeout
572  zmq::pollitem_t items[] = {{*m_pzmq->socket_zmq, 0, ZMQ_POLLIN, 0}};
573 
574  int nPoll = 0;
575  try {
576  nPoll = zmq::poll(&items[0], 1, static_cast<long>(lDoubling));
577  }
578  catch (std::exception& e) {
579  OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__,
580  e.what());
581  OT_FAIL;
582  }
583 
584  lDoubling *= 2;
585 
586  // If we got a reply, process it
587  if (items[0].revents & ZMQ_POLLIN) {
588  try {
589  bSuccessReceiving = m_pzmq->socket_zmq->recv(
590  &zmq_message,
591  ZMQ_NOBLOCK); // <=========== RECEIVE ===============
592  }
593  catch (std::exception& e) {
594  OTLog::vError("%s: Exception Caught: %s \n", __FUNCTION__,
595  e.what());
596  OT_FAIL;
597  }
599 
600  if (!bSuccessReceiving) {
601  if (!HandleReceivingError()) expect_reply = false;
602  }
603  else
604  break; // (Success -- we're done in this loop.)
605  }
606  else if (nReceiveTries == 0) {
607  // OTLog::Error("OTSocket::Receive: no message.\n");
608  expect_reply = false;
609  break;
610  }
611  else if ((-1) == nPoll) // error.
612  {
613  if (!HandlePollingError()) expect_reply = false;
614  }
615 
616  --nReceiveTries;
617  }
618  }
619 
620  if (bSuccessReceiving && (zmq_message.size() > 0))
621  strServerReply.MemSet(static_cast<const char*>(zmq_message.data()),
622  static_cast<uint32_t>(zmq_message.size()));
623 
624  return (bSuccessReceiving && (zmq_message.size() > 0));
625 }
626 
627 bool OTSocket_ZMQ_4::HandlePollingError()
628 {
629  bool bRetVal = false;
630 
631  switch (errno) {
632  // At least one of the members of the items array refers to a socket whose
633  // associated ØMQ context was terminated.
634  case ETERM:
635  OTLog::Error("OTSocket::HandlePollingError: Failure: At least one of "
636  "the members of the items array refers to a socket whose "
637  "associated ØMQ context was terminated. (Deleting and "
638  "re-creating the context.)\n");
639  NewContext();
640  break;
641  // The provided items was not valid (nullptr).
642  case EFAULT:
643  OTLog::Error("OTSocket::HandlePollingError: Failed: The provided "
644  "polling items were not valid (nullptr).\n");
645  break;
646  // The operation was interrupted by delivery of a signal before any events
647  // were available.
648  case EINTR:
649  OTLog::Error("OTSocket::HandlePollingError: The operation was "
650  "interrupted by delivery of a signal before any events "
651  "were available. Re-trying...\n");
652  bRetVal = true;
653  break;
654  default:
655  OTLog::Error(
656  "OTSocket::HandlePollingError: Default case. Re-trying...\n");
657  bRetVal = true;
658  break;
659  }
660  return bRetVal;
661 }
662 
663 bool OTSocket_ZMQ_4::HandleSendingError()
664 {
665  bool bRetVal = false;
666 
667  switch (errno) {
668  // Non-blocking mode was requested and the message cannot be sent at the
669  // moment.
670  case EAGAIN:
671  OTLog::vOutput(0, "OTSocket::HandleSendingError: Non-blocking mode was "
672  "requested and the message cannot be sent at the "
673  "moment. Re-trying...\n");
674  bRetVal = true;
675  break;
676  // The zmq_send() operation is not supported by this socket type.
677  case ENOTSUP:
678  OTLog::Error("OTSocket::HandleSendingError: failure: The zmq_send() "
679  "operation is not supported by this socket type.\n");
680  break;
681  // The zmq_send() operation cannot be performed on this socket at the moment
682  // due to the socket not being in the appropriate state. This error may
683  // occur with socket types that switch between several states, such as
684  // ZMQ_REP. See the messaging patterns section of zmq_socket(3) for more
685  // information.
686  case EFSM:
687  OTLog::vOutput(0, "OTSocket::HandleSendingError: The zmq_send() "
688  "operation cannot be performed on this socket at the "
689  "moment due to the socket not being in the "
690  "appropriate state. Deleting socket and "
691  "re-trying...\n");
692  RemakeSocket();
693  bRetVal = true;
694  break;
695  // The ØMQ context associated with the specified socket was terminated.
696  case ETERM:
697  OTLog::Error("OTSocket::HandleSendingError: The ØMQ context associated "
698  "with the specified socket was terminated. (Deleting and "
699  "re-creating the context and the socket, and trying "
700  "again.)\n");
701  RemakeSocket(true);
702  bRetVal = true;
703  break;
704  // The provided socket was invalid.
705  case ENOTSOCK:
706  OTLog::Error("OTSocket::HandleSendingError: The provided socket was "
707  "invalid. (Deleting socket and re-trying...)\n");
708  RemakeSocket();
709  bRetVal = true;
710  break;
711  // The operation was interrupted by delivery of a signal before the message
712  // was sent. Re-trying...
713  case EINTR:
714  OTLog::Error("OTSocket::HandleSendingError: The operation was "
715  "interrupted by delivery of a signal before the message "
716  "was sent. (Re-trying...)\n");
717  bRetVal = true;
718  break;
719  // Invalid message.
720  case EFAULT:
721  OTLog::Error("OTSocket::HandleSendingError: Failure: The provided "
722  "pollitems were not valid (nullptr).\n");
723  break;
724  default:
725  OTLog::Error(
726  "OTSocket::HandleSendingError: Default case. Re-trying...\n");
727  bRetVal = true;
728  break;
729  }
730  return bRetVal;
731 }
732 
733 bool OTSocket_ZMQ_4::HandleReceivingError()
734 {
735  bool bRetVal = false;
736 
737  switch (errno) {
738  // Non-blocking mode was requested and no messages are available at the
739  // moment.
740  case EAGAIN:
741  OTLog::vOutput(0, "OTSocket::HandleReceivingError: Non-blocking mode "
742  "was requested and no messages are available at the "
743  "moment. Re-trying...\n");
744  bRetVal = true;
745  break;
746  // The zmq_recv() operation is not supported by this socket type.
747  case ENOTSUP:
748  OTLog::Error("OTSocket::HandleReceivingError: Failure: The zmq_recv() "
749  "operation is not supported by this socket type.\n");
750  break;
751  // The zmq_recv() operation cannot be performed on this socket at the moment
752  // due to the socket not being in the appropriate state. This error may
753  // occur with socket types that switch between several states, such as
754  // ZMQ_REP. See the messaging patterns section of zmq_socket(3) for more
755  // information.
756  case EFSM:
757  OTLog::vOutput(0, "OTSocket::HandleReceivingError: The zmq_recv() "
758  "operation cannot be performed on this socket at the "
759  "moment due to the socket not being in the "
760  "appropriate state. (Deleting socket and "
761  "re-trying...)\n");
762  RemakeSocket();
763  {
764  OTASCIIArmor ascTemp(m_ascLastMsgSent);
765  bRetVal = Send(ascTemp);
766  }
767  break;
768  // The ØMQ context associated with the specified socket was terminated.
769  case ETERM:
770  OTLog::Error("OTSocket::HandleReceivingError: The ØMQ context "
771  "associated with the specified socket was terminated. "
772  "(Re-creating the context, and trying again...)\n");
773  RemakeSocket(true);
774  {
775  OTASCIIArmor ascTemp(m_ascLastMsgSent);
776  bRetVal = Send(ascTemp);
777  }
778  break;
779  // The provided socket was invalid.
780  case ENOTSOCK:
781  OTLog::Error("OTSocket::HandleReceivingError: The provided socket was "
782  "invalid. (Deleting socket and re-trying.)\n");
783  RemakeSocket();
784  {
785  OTASCIIArmor ascTemp(m_ascLastMsgSent);
786  bRetVal = Send(ascTemp);
787  }
788  break;
789  // The operation was interrupted by delivery of a signal before a message
790  // was available.
791  case EINTR:
792  OTLog::Error("OTSocket::HandleSendingError: The operation was "
793  "interrupted by delivery of a signal before the message "
794  "was sent. (Re-trying...)\n");
795  bRetVal = true;
796  break;
797  // The message passed to the function was invalid.
798  case EFAULT:
799  OTLog::Error("OTSocket::HandleReceivingError: Failure: The message "
800  "passed to the function was invalid.\n");
801  break;
802  default:
803  OTLog::Error(
804  "OTSocket::HandleReceivingError: Default case. Re-trying...\n");
805  bRetVal = true;
806  break;
807  }
808  return bRetVal;
809 }
810 
811 } // namespace opentxs
static EXPORT void vError(const char *szError,...)
Definition: OTLog.cpp:800
EXPORT bool RemakeSocket(const bool bNewContext=false)
int64_t m_lLatencyDelayAfter
Definition: OTSocket.hpp:190
OTString m_strConnectPath
Definition: OTSocket.hpp:198
int32_t m_nLatencyReceiveNoTries
Definition: OTSocket.hpp:189
int32_t m_nLatencySendNoTries
Definition: OTSocket.hpp:187
OTString m_strBindingPath
Definition: OTSocket.hpp:199
EXPORT uint32_t GetLength() const
Definition: OTString.cpp:1040
EXPORT bool Send(const OTASCIIArmor &ascEnvelope)
EXPORT bool Exists() const
Definition: OTString.cpp:1035
static EXPORT void Error(const char *szError)
Definition: OTLog.cpp:831
int64_t m_lLatencySendMs
Definition: OTSocket.hpp:186
EXPORT bool Compare(const char *compare) const
Definition: OTString.cpp:1102
EXPORT void Set(const char *data, uint32_t enforcedMaxLength=0)
Definition: OTString.cpp:1055
int64_t m_lLatencyReceiveMs
Definition: OTSocket.hpp:188
static EXPORT bool SleepMilliseconds(int64_t lMilliseconds)
Definition: OTLog.cpp:651
OTASCIIArmor m_ascLastMsgSent
Definition: OTSocket.hpp:201
#define OT_FAIL
Definition: Assert.hpp:139
EXPORT const char * Get() const
Definition: OTString.cpp:1045
EXPORT bool Receive(OTString &strServerReply)
EXPORT bool MemSet(const char *mem, uint32_t size)
Definition: OTString.cpp:967
static EXPORT void vOutput(int32_t nVerbosity, const char *szOutput,...)
Definition: OTLog.cpp:768
EXPORT bool NewContext()