void Connection::consume(char* input, size_t size) { char* buffer = input; size_t remaining = size; // A successful read means the connection is still responsive restart_terminate_timer(); while (remaining != 0) { ssize_t consumed = response_->decode(buffer, remaining); if (consumed <= 0) { notify_error("Error consuming message"); remaining = 0; continue; } if (response_->is_body_ready()) { ScopedPtr<ResponseMessage> response(response_.release()); response_.reset(new ResponseMessage()); LOG_TRACE("Consumed message type %s with stream %d, input %u, remaining %u on host %s", opcode_to_string(response->opcode()).c_str(), static_cast<int>(response->stream()), static_cast<unsigned int>(size), static_cast<unsigned int>(remaining), host_->address_string().c_str()); if (response->stream() < 0) { if (response->opcode() == CQL_OPCODE_EVENT) { listener_->on_event(static_cast<EventResponse*>(response->response_body().get())); } else { notify_error("Invalid response opcode for event stream: " + opcode_to_string(response->opcode())); } } else { Handler* handler = NULL; if (stream_manager_.get_pending_and_release(response->stream(), handler)) { switch (handler->state()) { case Handler::REQUEST_STATE_READING: maybe_set_keyspace(response.get()); pending_reads_.remove(handler); handler->stop_timer(); handler->set_state(Handler::REQUEST_STATE_DONE); handler->on_set(response.get()); handler->dec_ref(); break; case Handler::REQUEST_STATE_WRITING: // There are cases when the read callback will happen // before the write callback. If this happens we have // to allow the write callback to cleanup. maybe_set_keyspace(response.get()); handler->set_state(Handler::REQUEST_STATE_READ_BEFORE_WRITE); handler->on_set(response.get()); break; case Handler::REQUEST_STATE_TIMEOUT: pending_reads_.remove(handler); handler->set_state(Handler::REQUEST_STATE_DONE); handler->dec_ref(); break; case Handler::REQUEST_STATE_TIMEOUT_WRITE_OUTSTANDING: // We must wait for the write callback before we can do the cleanup handler->set_state(Handler::REQUEST_STATE_READ_BEFORE_WRITE); break; default: assert(false && "Invalid request state after receiving response"); break; } } else { notify_error("Invalid stream ID"); } } } remaining -= consumed; buffer += consumed; } }