1
0
Fork 0

fix errors in vpp protocol

This commit is contained in:
Jan Christoph Uhde 2016-08-09 19:09:24 +02:00
parent 0e5b455159
commit 8f6ff64d00
9 changed files with 88 additions and 33 deletions

View File

@ -26,6 +26,7 @@
#include "GeneralServer/GeneralServer.h"
#include "GeneralServer/GeneralServerFeature.h"
#include "GeneralServer/VppCommTask.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/SchedulerFeature.h"
#include "Ssl/SslServerFeature.h"
@ -64,11 +65,11 @@ bool GeneralListenTask::handleConnected(TRI_socket_t socket,
switch (_connectionType) {
case ConnectionType::VPPS:
commTask =
new HttpCommTask(_server, socket, std::move(info), _keepAliveTimeout);
new VppCommTask(_server, socket, std::move(info), _keepAliveTimeout);
break;
case ConnectionType::VPP:
commTask =
new HttpCommTask(_server, socket, std::move(info), _keepAliveTimeout);
new VppCommTask(_server, socket, std::move(info), _keepAliveTimeout);
break;
case ConnectionType::HTTPS:
commTask = new HttpsCommTask(_server, socket, std::move(info),

View File

@ -118,9 +118,17 @@ std::unique_ptr<basics::StringBuffer> createChunkForNetworkMultiFollow(
}
}
VppCommTask::VppCommTask(GeneralServer* server, TRI_socket_t sock,
ConnectionInfo&& info, double timeout)
: Task("VppCommTask"),
GeneralCommTask(server, sock, std::move(info), timeout) {
_protocol = "vpp";
// connectionStatisticsAgentSetVpp();
}
void VppCommTask::addResponse(VppResponse* response, bool isError) {
if (isError) {
// FIXME
// FIXME (obi)
// what do we need to do?
// clean read buffer? reset process read cursor
}
@ -130,16 +138,17 @@ void VppCommTask::addResponse(VppResponse* response, bool isError) {
std::vector<VPackSlice> slices;
slices.push_back(response_message._header);
// if payload != Slice()
slices.push_back(response_message._payload);
uint32_t message_length = 0;
for (auto const& slice : slices) {
message_length = slice.byteSize();
message_length += slice.byteSize();
}
// FIXME
// FIXME (obi)
// If the message is big we will create many small chunks in a loop.
// For the first tests we just send single Messages
StringBuffer tmp(TRI_UNKNOWN_MEM_ZONE, message_length, false);
@ -177,7 +186,7 @@ VppCommTask::ChunkHeader VppCommTask::readChunkHeader() {
cursor += sizeof(header._messageID);
// extract total len of message
if (header._isFirst && header._chunk == 1) {
if (header._isFirst && header._chunk > 1) {
std::memcpy(&header._messageLength, cursor, sizeof(header._messageLength));
cursor += sizeof(header._messageLength);
} else {
@ -233,13 +242,15 @@ bool VppCommTask::processRead() {
// CASE 1: message is in one chunk
if (chunkHeader._isFirst && chunkHeader._chunk == 1) {
std::size_t payloadOffset = findAndValidateVPacks(vpackBegin, chunkEnd);
VPackMessage message;
message._id = chunkHeader._messageID;
message._buffer.append(vpackBegin, std::distance(vpackBegin, chunkEnd));
message._header = VPackSlice(message._buffer.data());
if (payloadOffset) {
message._payload = VPackSlice(message._buffer.data() + payloadOffset);
}
VPackValidator val;
val.validate(message._header.begin(), message._header.byteSize());
do_execute = true;
}
// CASE 2: message is in multiple chunks
@ -308,6 +319,7 @@ bool VppCommTask::processRead() {
// for now we can handle only one request at a time
// lock _request???? REVIEW (fc)
LOG(ERR) << message._header.toJson();
_request = new VppRequest(_connectionInfo, std::move(message));
GeneralServerFeature::HANDLER_FACTORY->setRequestContext(_request);
_request->setClientTaskId(_taskId);

View File

@ -56,6 +56,7 @@ class VppCommTask : public GeneralCommTask {
protected:
void completedWriteBuffer() override final;
virtual void handleChunk(char const*, size_t) {}
private:
// resets the internal state this method can be called to clean up when the

View File

@ -86,7 +86,8 @@ std::string Endpoint::unifiedForm(std::string const& specification) {
}
// read protocol from string
if (StringUtils::isPrefix(copy, "http+") || StringUtils::isPrefix(copy, "http@")) {
if (StringUtils::isPrefix(copy, "http+") ||
StringUtils::isPrefix(copy, "http@")) {
protocol = TransportType::HTTP;
prefix = "http+";
copy = copy.substr(5);
@ -94,7 +95,7 @@ std::string Endpoint::unifiedForm(std::string const& specification) {
if (StringUtils::isPrefix(copy, "vpp+")) {
protocol = TransportType::VPP;
prefix = "vsp+";
prefix = "vpp+";
copy = copy.substr(4);
}
@ -159,10 +160,10 @@ std::string Endpoint::unifiedForm(std::string const& specification) {
// hostname only
if (protocol == TransportType::HTTP) {
return prefix + copy + ":" + StringUtils::itoa(EndpointIp::_defaultPortHttp);
} else {
return prefix + copy + ":" +
StringUtils::itoa(EndpointIp::_defaultPortVpp);
StringUtils::itoa(EndpointIp::_defaultPortHttp);
} else {
return prefix + copy + ":" + StringUtils::itoa(EndpointIp::_defaultPortVpp);
}
}
@ -323,7 +324,8 @@ std::string const Endpoint::defaultEndpoint(TransportType type) {
StringUtils::itoa(EndpointIp::_defaultPortVpp);
default: {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid transport type");
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"invalid transport type");
}
}
@ -379,7 +381,8 @@ bool Endpoint::setSocketFlags(TRI_socket_t s) {
return true;
}
std::ostream& operator<<(std::ostream& stream, arangodb::Endpoint::TransportType type) {
std::ostream& operator<<(std::ostream& stream,
arangodb::Endpoint::TransportType type) {
switch (type) {
case arangodb::Endpoint::TransportType::HTTP:
stream << "http";
@ -391,7 +394,8 @@ std::ostream& operator<<(std::ostream& stream, arangodb::Endpoint::TransportType
return stream;
}
std::ostream& operator<<(std::ostream& stream, arangodb::Endpoint::EndpointType type) {
std::ostream& operator<<(std::ostream& stream,
arangodb::Endpoint::EndpointType type) {
switch (type) {
case arangodb::Endpoint::EndpointType::SERVER:
stream << "server";
@ -403,7 +407,8 @@ std::ostream& operator<<(std::ostream& stream, arangodb::Endpoint::EndpointType
return stream;
}
std::ostream& operator<<(std::ostream& stream, arangodb::Endpoint::EncryptionType type) {
std::ostream& operator<<(std::ostream& stream,
arangodb::Endpoint::EncryptionType type) {
switch (type) {
case arangodb::Endpoint::EncryptionType::NONE:
stream << "none";
@ -415,7 +420,8 @@ std::ostream& operator<<(std::ostream& stream, arangodb::Endpoint::EncryptionTyp
return stream;
}
std::ostream& operator<<(std::ostream& stream, arangodb::Endpoint::DomainType type) {
std::ostream& operator<<(std::ostream& stream,
arangodb::Endpoint::DomainType type) {
switch (type) {
case arangodb::Endpoint::DomainType::UNIX:
stream << "unix";

View File

@ -63,11 +63,11 @@ class GeneralRequest {
enum class RequestType {
DELETE_REQ = 0, // windows redefines DELETE
GET,
HEAD,
OPTIONS,
POST,
PUT,
HEAD,
PATCH,
OPTIONS,
VSTREAM_CRED,
VSTREAM_REGISTER,
VSTREAM_STATUS,

View File

@ -182,6 +182,19 @@ class GeneralResponse {
arangodb::velocypack::Options const& = arangodb::
velocypack::Options::Defaults) = 0;
virtual void addPayload(VPackSlice const& slice) {
_vpackPayloads.emplace_back(slice.byteSize());
std::memcpy(&_vpackPayloads.back(), slice.start(), slice.byteSize());
};
virtual void addPayload(VPackBuffer<uint8_t>&& buffer) {
_vpackPayloads.push_back(std::move(buffer));
};
virtual void addHeaderInformation(std::string s /* any or variant */){
};
// virtual void setPayload(ContentType contentType,
// VPackBuffer<uint8_t>&& sliceBuffer,
// bool generateBody = true,
@ -192,6 +205,8 @@ class GeneralResponse {
ResponseCode _responseCode; // http response code
std::unordered_map<std::string, std::string>
_headers; // headers/metadata map
std::vector<VPackBuffer<uint8_t>> _vpackPayloads;
};
}

View File

@ -38,7 +38,7 @@ struct VPackMessage {
VPackMessage(VPackBuffer<uint8_t>&& buff, VPackSlice head, VPackSlice pay,
uint64_t id)
: _buffer(std::move(buff)), _header(head), _payload(pay), _id(id) {}
VPackMessage(VPackMessage&&) = default; // not necessary just to make sure!
VPackMessage(VPackMessage&& other) = default;
VPackBuffer<uint8_t> _buffer;
VPackSlice _header;

View File

@ -31,12 +31,17 @@
#include <velocypack/Validator.h>
#include <velocypack/velocypack-aliases.h>
#include "Basics/conversions.h"
#include "Basics/StaticStrings.h"
#include "Basics/StringRef.h"
#include "Basics/StringUtils.h"
#include "Basics/conversions.h"
#include "Basics/tri-strings.h"
#include "Meta/conversion.h"
#include "Logger/Logger.h"
// TODO (obi)
// - REMOVE TRI_ASSERT
using namespace arangodb;
using namespace arangodb::basics;
@ -60,16 +65,15 @@ VppRequest::VppRequest(ConnectionInfo const& connectionInfo,
: GeneralRequest(connectionInfo),
_message(std::move(message)),
_headers(nullptr) {
if (message._payload != VPackSlice::noneSlice()) {
_protocol = "vpp";
_contentType = ContentType::VPACK;
_contentTypeResponse = ContentType::VPACK;
_protocol = "vpp";
parseHeaderInformation();
}
_user = "root";
}
VPackSlice VppRequest::payload(VPackOptions const* options) {
// TODO - handle options??
// TODO (obi)- handle options??
return _message._payload;
}
@ -78,8 +82,12 @@ std::unordered_map<std::string, std::string> const& VppRequest::headers()
if (!_headers) {
using namespace std;
_headers = make_unique<unordered_map<string, string>>();
LOG(ERR) << _message._header.toJson();
TRI_ASSERT(_message._header.isObject());
for (auto const& it : VPackObjectIterator(_message._header)) {
VPackSlice meta = _message._header.get("meta");
// TRI_ASSERT(meta.isObject());
for (auto const& it : VPackObjectIterator(meta)) {
TRI_ASSERT(it.key.isString());
_headers->emplace(it.key.copyString(), it.value.copyString());
}
}
@ -99,7 +107,13 @@ std::string const& VppRequest::header(std::string const& key) const {
void VppRequest::parseHeaderInformation() {
using namespace std;
TRI_ASSERT(_message._header.isObject());
auto& vHeader = _message._header;
TRI_ASSERT(vHeader.isObject());
_databaseName = vHeader.get("database").copyString();
_requestPath = vHeader.get("request").copyString();
_type = meta::toEnum<RequestType>(vHeader.get("requestType").getInt());
VPackSlice params = _message._header.get("parameter");
TRI_ASSERT(params.isObject());
for (auto const& it : VPackObjectIterator(params)) {

View File

@ -1,4 +1,4 @@
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
@ -61,6 +61,12 @@ void VppResponse::setPayload(ContentType contentType,
arangodb::velocypack::Slice const& slice,
bool generateBody, VPackOptions const& options) {
if (generateBody) {
// addPayload(slice);
if (_payload.empty()) {
throw std::logic_error("payload should be empty!!");
}
_payload.append(slice.startAs<char>(),
std::distance(slice.begin(), slice.end()));
}
};