| 177 | } |
| 178 | |
| 179 | bool TorControlConnection::ProcessBuffer() |
| 180 | { |
| 181 | util::LineReader reader(m_recv_buffer, MAX_LINE_LENGTH); |
| 182 | auto start = reader.it; |
| 183 | |
| 184 | while (auto line = reader.ReadLine()) { |
| 185 | if (m_message.lines.size() == MAX_LINE_COUNT) { |
| 186 | throw std::runtime_error(strprintf("Control port reply exceeded %d lines, disconnecting", MAX_LINE_COUNT)); |
| 187 | } |
| 188 | // Skip short lines |
| 189 | if (line->size() < 4) continue; |
| 190 | |
| 191 | // Parse: <code><separator><data> |
| 192 | // <status>(-|+| )<data> |
| 193 | m_message.code = ToIntegral<int>(line->substr(0, 3)).value_or(0); |
| 194 | m_message.lines.emplace_back(line->substr(4)); |
| 195 | char separator = (*line)[3]; // '-', '+', or ' ' |
| 196 | |
| 197 | if (separator == ' ') { |
| 198 | if (m_message.code >= 600) { |
| 199 | // Async notifications are currently unused |
| 200 | // Synchronous and asynchronous messages are never interleaved |
| 201 | LogDebug(BCLog::TOR, "Received async notification %i", m_message.code); |
| 202 | } else if (!m_reply_handlers.empty()) { |
| 203 | // Invoke reply handler with message |
| 204 | m_reply_handlers.front()(*this, m_message); |
| 205 | m_reply_handlers.pop_front(); |
| 206 | } else { |
| 207 | LogDebug(BCLog::TOR, "Received unexpected sync reply %i", m_message.code); |
| 208 | } |
| 209 | m_message.Clear(); |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | m_recv_buffer.erase(m_recv_buffer.begin(), m_recv_buffer.begin() + std::distance(start, reader.it)); |
| 214 | return true; |
| 215 | } |
| 216 | |
| 217 | bool TorControlConnection::Command(const std::string &cmd, const ReplyHandlerCB& reply_handler) |
| 218 | { |