memgraph/src/communication/client.hpp
2022-03-14 15:47:41 +01:00

171 lines
4.3 KiB
C++

// Copyright 2022 Memgraph Ltd.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
// License, and you may not use this file except in compliance with the Business Source License.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#pragma once
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include "communication/buffer.hpp"
#include "communication/context.hpp"
#include "communication/init.hpp"
#include "io/network/endpoint.hpp"
#include "io/network/socket.hpp"
namespace memgraph::communication {
/**
* This class implements a generic network Client.
* It uses blocking sockets and provides an API that can be used to receive/send
* data over the network connection.
*
* NOTE: If you use this client you **must** create `memgraph::communication::SSLInit`
* from the `main` function before using the client!
*/
class Client final {
public:
explicit Client(ClientContext *context);
~Client();
Client(const Client &) = delete;
Client(Client &&) = delete;
Client &operator=(const Client &) = delete;
Client &operator=(Client &&) = delete;
/**
* This function connects to a remote server and returns whether the connect
* succeeded.
*/
bool Connect(const io::network::Endpoint &endpoint);
/**
* This function returns `true` if the socket is in an error state.
*/
bool ErrorStatus();
/**
* This function returns `true` if the socket is connected to a remote host.
*/
bool IsConnected();
/**
* This function shuts down the socket.
*/
void Shutdown();
/**
* This function closes the socket.
*/
void Close();
/**
* This function is used to receive exactly `len` bytes from the socket and
* stores it in an internal buffer. If `exactly_len` is set to `false` then
* less than `len` bytes can be received. It returns `true` if the read
* succeeded and `false` if it didn't.
*/
bool Read(size_t len, bool exactly_len = true);
/**
* This function returns a pointer to the read data that is currently stored
* in the client.
*/
uint8_t *GetData();
/**
* This function returns the size of the read data that is currently stored in
* the client.
*/
size_t GetDataSize();
/**
* This function removes first `len` bytes from the data buffer.
*/
void ShiftData(size_t len);
/**
* This function clears the data buffer.
*/
void ClearData();
/**
* This function writes data to the socket.
* TODO (mferencevic): the `have_more` flag currently isn't supported when
* using OpenSSL
*/
bool Write(const uint8_t *data, size_t len, bool have_more = false);
/**
* This function writes data to the socket.
*/
bool Write(const std::string &str, bool have_more = false);
const io::network::Endpoint &endpoint();
private:
void ReleaseSslObjects();
io::network::Socket socket_;
Buffer buffer_;
ClientContext *context_;
SSL *ssl_{nullptr};
BIO *bio_{nullptr};
};
/**
* This class provides a stream-like input side object to the client.
*/
class ClientInputStream final {
public:
ClientInputStream(Client &client);
ClientInputStream(const ClientInputStream &) = delete;
ClientInputStream(ClientInputStream &&) = delete;
ClientInputStream &operator=(const ClientInputStream &) = delete;
ClientInputStream &operator=(ClientInputStream &&) = delete;
uint8_t *data();
size_t size() const;
void Shift(size_t len);
void Clear();
private:
Client &client_;
};
/**
* This class provides a stream-like output side object to the client.
*/
class ClientOutputStream final {
public:
ClientOutputStream(Client &client);
ClientOutputStream(const ClientOutputStream &) = delete;
ClientOutputStream(ClientOutputStream &&) = delete;
ClientOutputStream &operator=(const ClientOutputStream &) = delete;
ClientOutputStream &operator=(ClientOutputStream &&) = delete;
bool Write(const uint8_t *data, size_t len, bool have_more = false);
bool Write(const std::string &str, bool have_more = false);
private:
Client &client_;
};
} // namespace memgraph::communication