IpcServerBase.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file IpcServerBase.cpp
  15. * @authors:
  16. * Arkadiy Paronyan <arkadiy@ethdev.com>
  17. * @date 2015
  18. */
  19. #include "IpcServerBase.h"
  20. #include <cstdlib>
  21. #include <cstdio>
  22. #include <string>
  23. #include <libdevcore/Guards.h>
  24. #include <libdevcore/Log.h>
  25. using namespace std;
  26. using namespace jsonrpc;
  27. using namespace dev;
  28. int const c_bufferSize = 1024;
  29. struct IpcSendChannel: public LogChannel { static const char* name() { return "I>"; } static const int verbosity = 10; };
  30. struct IpcReceiveChannel: public LogChannel { static const char* name() { return "I<"; } static const int verbosity = 10; };
  31. #define cipcs dev::LogOutputStream<IpcSendChannel, true>()
  32. #define cipcr dev::LogOutputStream<IpcReceiveChannel, true>()
  33. template <class S> IpcServerBase<S>::IpcServerBase(string const& _path):
  34. m_path(_path)
  35. {
  36. }
  37. template <class S> bool IpcServerBase<S>::StartListening()
  38. {
  39. if (!m_running)
  40. {
  41. m_running = true;
  42. m_listeningThread = std::thread([this](){ Listen(); });
  43. return true;
  44. }
  45. return false;
  46. }
  47. template <class S> bool IpcServerBase<S>::StopListening()
  48. {
  49. if (m_running)
  50. {
  51. m_running = false;
  52. DEV_GUARDED(x_sockets)
  53. {
  54. for (S s : m_sockets)
  55. CloseConnection(s);
  56. m_sockets.clear();
  57. }
  58. m_listeningThread.join();
  59. return true;
  60. }
  61. return false;
  62. }
  63. template <class S> bool IpcServerBase<S>::SendResponse(string const& _response, void* _addInfo)
  64. {
  65. bool fullyWritten = false;
  66. bool errorOccured = false;
  67. S socket = (S)(reinterpret_cast<intptr_t>(_addInfo));
  68. string toSend = _response;
  69. do
  70. {
  71. size_t bytesWritten = Write(socket, toSend);
  72. if (bytesWritten == 0)
  73. errorOccured = true;
  74. else if (bytesWritten < toSend.size())
  75. {
  76. int len = toSend.size() - bytesWritten;
  77. toSend = toSend.substr(bytesWritten + sizeof(char), len);
  78. }
  79. else
  80. fullyWritten = true;
  81. } while (!fullyWritten && !errorOccured);
  82. cipcs << _response;
  83. return fullyWritten && !errorOccured;
  84. }
  85. template <class S> void IpcServerBase<S>::GenerateResponse(S _connection)
  86. {
  87. char buffer[c_bufferSize];
  88. string request;
  89. bool escape = false;
  90. bool inString = false;
  91. size_t i = 0;
  92. int depth = 0;
  93. size_t nbytes = 0;
  94. do
  95. {
  96. nbytes = Read(_connection, buffer, c_bufferSize);
  97. if (nbytes <= 0)
  98. break;
  99. request.append(buffer, nbytes);
  100. while (i < request.size())
  101. {
  102. char c = request[i];
  103. if (c == '\"' && !inString)
  104. {
  105. inString = true;
  106. escape = false;
  107. }
  108. else if (c == '\"' && inString && !escape)
  109. {
  110. inString = false;
  111. escape = false;
  112. }
  113. else if (inString && c == '\\' && !escape)
  114. {
  115. escape = true;
  116. }
  117. else if (inString)
  118. {
  119. escape = false;
  120. }
  121. else if (!inString && (c == '{' || c == '['))
  122. {
  123. depth++;
  124. }
  125. else if (!inString && (c == '}' || c == ']'))
  126. {
  127. depth--;
  128. if (depth == 0)
  129. {
  130. std::string r = request.substr(0, i + 1);
  131. request.erase(0, i + 1);
  132. cipcr << r;
  133. OnRequest(r, reinterpret_cast<void*>((intptr_t)_connection));
  134. i = 0;
  135. continue;
  136. }
  137. }
  138. i++;
  139. }
  140. } while (true);
  141. DEV_GUARDED(x_sockets)
  142. m_sockets.erase(_connection);
  143. }
  144. namespace dev
  145. {
  146. template class IpcServerBase<int>;
  147. template class IpcServerBase<void*>;
  148. }