mirror of https://gitee.com/bigwinds/arangodb
144 lines
5.1 KiB
C++
144 lines
5.1 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
|
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// @author Jan Christoph Uhde
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef ARANGOD_GENERAL_SERVER_VST_COMM_TASK_H
|
|
#define ARANGOD_GENERAL_SERVER_VST_COMM_TASK_H 1
|
|
|
|
#include "Basics/Common.h"
|
|
#include "GeneralServer/GeneralCommTask.h"
|
|
#include "lib/Rest/VstMessage.h"
|
|
#include "lib/Rest/VstRequest.h"
|
|
#include "lib/Rest/VstResponse.h"
|
|
|
|
#include <stdexcept>
|
|
|
|
namespace arangodb {
|
|
|
|
namespace rest {
|
|
|
|
class VstCommTask final : public GeneralCommTask {
|
|
public:
|
|
VstCommTask(GeneralServer& server, std::unique_ptr<Socket> socket,
|
|
ConnectionInfo&&, double timeout,
|
|
ProtocolVersion protocolVersion, bool skipSocketInit = false);
|
|
|
|
arangodb::Endpoint::TransportType transportType() override {
|
|
return arangodb::Endpoint::TransportType::VST;
|
|
}
|
|
|
|
// whether or not this task can mix sync and async I/O
|
|
bool canUseMixedIO() const override;
|
|
|
|
protected:
|
|
// read data check if chunk and message are complete
|
|
// if message is complete execute a request
|
|
bool processRead(double startTime) override;
|
|
|
|
std::unique_ptr<GeneralResponse> createResponse(rest::ResponseCode,
|
|
uint64_t messageId) override final;
|
|
|
|
// @brief send simple response including response body
|
|
void addSimpleResponse(rest::ResponseCode, rest::ContentType, uint64_t messageId,
|
|
velocypack::Buffer<uint8_t>&&) override;
|
|
|
|
// convert from GeneralResponse to VstResponse ad dispatch request to class
|
|
// internal addResponse
|
|
void addResponse(GeneralResponse&, RequestStatistics*) override;
|
|
|
|
bool allowDirectHandling() const override final { return false; }
|
|
|
|
private:
|
|
// process the VST 1000 request type
|
|
void handleAuthHeader(VPackSlice const& header, uint64_t messageId);
|
|
|
|
// reets the internal state this method can be called to clean up when the
|
|
// request handling aborts prematurely
|
|
void closeTask(rest::ResponseCode code = rest::ResponseCode::SERVER_ERROR);
|
|
|
|
private:
|
|
using MessageID = uint64_t;
|
|
|
|
struct IncompleteVPackMessage {
|
|
IncompleteVPackMessage(uint32_t length, std::size_t numberOfChunks)
|
|
: _length(length),
|
|
_buffer(_length),
|
|
_numberOfChunks(numberOfChunks),
|
|
_currentChunk(0) {}
|
|
uint32_t _length; // length of total message in bytes
|
|
VPackBuffer<uint8_t> _buffer;
|
|
std::size_t _numberOfChunks;
|
|
std::size_t _currentChunk;
|
|
};
|
|
std::unordered_map<MessageID, IncompleteVPackMessage> _incompleteMessages;
|
|
|
|
static size_t const _bufferLength = 4096UL;
|
|
static size_t const _chunkMaxBytes = 1000UL;
|
|
struct ProcessReadVariables {
|
|
ProcessReadVariables()
|
|
: _currentChunkLength(0),
|
|
_readBufferOffset(0),
|
|
_cleanupLength(_bufferLength - _chunkMaxBytes - 1) {}
|
|
uint32_t _currentChunkLength; // size of chunk processed or 0 when
|
|
// expecting new chunk
|
|
size_t _readBufferOffset; // data up to this position has been processed
|
|
std::size_t _cleanupLength; // length of data after that the read buffer
|
|
// will be cleaned
|
|
};
|
|
ProcessReadVariables _processReadVariables;
|
|
|
|
struct ChunkHeader {
|
|
std::size_t _headerLength;
|
|
uint32_t _chunkLength;
|
|
uint32_t _chunk;
|
|
uint64_t _messageID;
|
|
uint64_t _messageLength;
|
|
bool _isFirst;
|
|
};
|
|
bool isChunkComplete(char*); // sub-function of processRead
|
|
ChunkHeader readChunkHeader(); // sub-function of processRead
|
|
void replyToIncompleteMessages();
|
|
|
|
// Returns true if and only if there was no error, if false is returned,
|
|
// the connection is closed
|
|
bool getMessageFromSingleChunk(ChunkHeader const& chunkHeader,
|
|
VstInputMessage& message, bool& doExecute,
|
|
char const* vpackBegin, char const* chunkEnd);
|
|
|
|
// Returns true if and only if there was no error, if false is returned,
|
|
// the connection is closed
|
|
bool getMessageFromMultiChunks(ChunkHeader const& chunkHeader,
|
|
VstInputMessage& message, bool& doExecute,
|
|
char const* vpackBegin, char const* chunkEnd);
|
|
|
|
private:
|
|
/// Is the current user authorized
|
|
bool _authorized;
|
|
rest::AuthenticationMethod _authMethod;
|
|
ProtocolVersion _protocolVersion;
|
|
uint32_t _maxChunkSize;
|
|
};
|
|
} // namespace rest
|
|
} // namespace arangodb
|
|
|
|
#endif
|