| 132 | } |
| 133 | |
| 134 | void TorControlConnection::readcb(struct bufferevent *bev, void *ctx) |
| 135 | { |
| 136 | TorControlConnection *self = static_cast<TorControlConnection*>(ctx); |
| 137 | struct evbuffer *input = bufferevent_get_input(bev); |
| 138 | size_t n_read_out = 0; |
| 139 | char *line; |
| 140 | assert(input); |
| 141 | // If there is not a whole line to read, evbuffer_readln returns nullptr |
| 142 | while((line = evbuffer_readln(input, &n_read_out, EVBUFFER_EOL_CRLF)) != nullptr) |
| 143 | { |
| 144 | std::string s(line, n_read_out); |
| 145 | free(line); |
| 146 | if (s.size() < 4) // Short line |
| 147 | continue; |
| 148 | // <status>(-|+| )<data><CRLF> |
| 149 | self->message.code = atoi(s.substr(0,3)); |
| 150 | self->message.lines.push_back(s.substr(4)); |
| 151 | char ch = s[3]; // '-','+' or ' ' |
| 152 | if (ch == ' ') { |
| 153 | // Final line, dispatch reply and clean up |
| 154 | if (self->message.code >= 600) { |
| 155 | // Dispatch async notifications to async handler |
| 156 | // Synchronous and asynchronous messages are never interleaved |
| 157 | self->async_handler(*self, self->message); |
| 158 | } else { |
| 159 | if (!self->reply_handlers.empty()) { |
| 160 | // Invoke reply handler with message |
| 161 | self->reply_handlers.front()(*self, self->message); |
| 162 | self->reply_handlers.pop_front(); |
| 163 | } else { |
| 164 | LogPrint(BCLog::TOR, "tor: Received unexpected sync reply %i\n", self->message.code); |
| 165 | } |
| 166 | } |
| 167 | self->message.Clear(); |
| 168 | } |
| 169 | } |
| 170 | // Check for size of buffer - protect against memory exhaustion with very long lines |
| 171 | // Do this after evbuffer_readln to make sure all full lines have been |
| 172 | // removed from the buffer. Everything left is an incomplete line. |
| 173 | if (evbuffer_get_length(input) > MAX_LINE_LENGTH) { |
| 174 | LogPrintf("tor: Disconnecting because MAX_LINE_LENGTH exceeded\n"); |
| 175 | self->Disconnect(); |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | void TorControlConnection::eventcb(struct bufferevent *bev, short what, void *ctx) |
| 180 | { |