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