-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Interim checkin with basic address and protocol classes
- Loading branch information
Showing
15 changed files
with
314 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#include "address.h" | ||
|
||
const iggy::net::protocol::ProtocolDefinition& iggy::net::address::LogicalAddress::getProtocolDefinition() const { | ||
return this->protocolProvider->getProtocolDefinition(this->getProtocol()); | ||
} | ||
|
||
iggy::net::address::LogicalAddress::LogicalAddress(const std::string& url, const iggy::net::protocol::ProtocolProvider* protocolProvider) { | ||
auto parse_result = ada::parse<ada::url>(url); | ||
if (!parse_result) { | ||
throw std::invalid_argument("Invalid URL: " + url); | ||
} | ||
auto value = parse_result.value(); | ||
auto protocol = value.get_protocol(); | ||
if (!protocolProvider->isSupported(protocol)) { | ||
throw std::invalid_argument("Unsupported protocol: " + protocol); | ||
} | ||
this->url = value; | ||
this->protocolProvider = protocolProvider; | ||
} | ||
|
||
const unsigned short iggy::net::address::LogicalAddress::getPort() const { | ||
if (url.get_port().empty()) { | ||
return this->getProtocolDefinition().getDefaultPort(); | ||
} else { | ||
int port = std::stoi(url.get_port()); | ||
|
||
// this should not happen if ada::parse is working correctly | ||
if (port < 0 || port > 65535) { | ||
throw std::out_of_range("Port number out of range"); | ||
} | ||
|
||
return port; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#pragma once | ||
|
||
#include <ada.h> | ||
#include <vector> | ||
#include "protocol.h" | ||
#include "transport.h" | ||
|
||
namespace iggy { | ||
namespace net { | ||
namespace address { | ||
|
||
/*** | ||
* @brief Logical address used in configuration and API to specify desired transport in a compact way, e.g. iggy:quic://localhost:8080. | ||
*/ | ||
class LogicalAddress { | ||
private: | ||
ada::url url; | ||
const iggy::net::protocol::ProtocolProvider* protocolProvider; | ||
|
||
const iggy::net::protocol::ProtocolDefinition& getProtocolDefinition() const; | ||
public: | ||
/** | ||
* @brief Construct a logical address from a URL. | ||
* @param url URL to parse. | ||
* @param protocolProvider Context object providing supported protocols and default ports. | ||
* @throws std::invalid_argument if the URL is invalid or the protocol is unknown. | ||
*/ | ||
LogicalAddress(const std::string& url, const iggy::net::protocol::ProtocolProvider* protocolProvider); | ||
|
||
/** | ||
* @brief Gets the protocol; you have a guarantee that it will be one of the supported protocols from ProtocolProvider. | ||
*/ | ||
const std::string getProtocol() const noexcept { return url.get_protocol(); } | ||
|
||
/** | ||
* @brief Gets the hostname to connect to or raw IP address. | ||
*/ | ||
const std::string getHost() const noexcept { return url.get_hostname(); } | ||
|
||
/** | ||
* @brief Gets the port to connect to; protocol default port will be substituted if not specified. | ||
*/ | ||
const unsigned short getPort() const; | ||
}; | ||
}; // namespace address | ||
}; // namespace net | ||
}; // namespace iggy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#include "iggy.h" | ||
|
||
iggy::net::IggyProtocolProvider::IggyProtocolProvider() { | ||
for (const auto& protocol : this->supportedProtocols) { | ||
this->supportedProtocolLookup[protocol.getName()] = protocol; | ||
} | ||
} | ||
|
||
const std::vector<iggy::net::protocol::ProtocolDefinition>& iggy::net::IggyProtocolProvider::getSupportedProtocols() const { | ||
return this->supportedProtocols; | ||
} | ||
|
||
const iggy::net::protocol::ProtocolDefinition& iggy::net::IggyProtocolProvider::getProtocolDefinition(const std::string& protocol) const { | ||
auto normalizedName = iggy::net::protocol::normalizeProtocolName(protocol); | ||
auto it = this->supportedProtocolLookup.find(normalizedName); | ||
if (it != this->supportedProtocolLookup.end()) { | ||
return it->second; | ||
} else { | ||
throw std::invalid_argument("Unsupported protocol: " + protocol); | ||
} | ||
} | ||
|
||
const bool iggy::net::IggyProtocolProvider::isSupported(const std::string& protocol) const { | ||
return this->supportedProtocolLookup.count(iggy::net::protocol::normalizeProtocolName(protocol)) > 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#pragma once | ||
#include <map> | ||
#include <vector> | ||
#include "address.h" | ||
|
||
namespace iggy { | ||
namespace net { | ||
|
||
const unsigned short DEFAULT_HTTP_PORT = 3000; | ||
const unsigned short DEFAULT_TCP_PORT = 8090; | ||
const unsigned short DEFAULT_QUIC_PORT = 8080; | ||
|
||
const std::string QUIC_PROTOCOL = "iggy:quic"; | ||
const std::string TCP_PROTOCOL = "iggy:tcp"; | ||
const std::string TCP_TLS_PROTOCOL = "iggy:tcp+tls"; | ||
const std::string HTTP_PROTOCOL = "iggy:http"; | ||
const std::string HTTP_TLS_PROTOCOL = "iggy:http+tls"; | ||
|
||
using iggy::net::protocol::MessageEncoding; | ||
using iggy::net::protocol::ProtocolDefinition; | ||
|
||
/** | ||
* @brief Provider that declares support and offers defaults for all Iggy C++ supported protocols. | ||
* | ||
* At this time we support iggy:quic, iggy:tcp (binary messaging) and iggy:http (with JSON messaging). | ||
*/ | ||
class IggyProtocolProvider : iggy::net::protocol::ProtocolProvider { | ||
private: | ||
std::vector<ProtocolDefinition> supportedProtocols = { | ||
ProtocolDefinition(QUIC_PROTOCOL, DEFAULT_QUIC_PORT, iggy::net::transport::QUIC, true, MessageEncoding::BINARY), | ||
ProtocolDefinition(TCP_PROTOCOL, DEFAULT_TCP_PORT, iggy::net::transport::TCP, false, MessageEncoding::BINARY), | ||
ProtocolDefinition(TCP_TLS_PROTOCOL, DEFAULT_TCP_PORT, iggy::net::transport::TCP, true, MessageEncoding::BINARY), | ||
ProtocolDefinition(HTTP_PROTOCOL, DEFAULT_HTTP_PORT, iggy::net::transport::HTTP, false, MessageEncoding::TEXT), | ||
ProtocolDefinition(HTTP_TLS_PROTOCOL, DEFAULT_HTTP_PORT, iggy::net::transport::HTTP, true, MessageEncoding::TEXT)}; | ||
std::map<std::string, ProtocolDefinition> supportedProtocolLookup; | ||
|
||
public: | ||
IggyProtocolProvider(); | ||
const std::vector<ProtocolDefinition>& getSupportedProtocols() const override; | ||
const ProtocolDefinition& getProtocolDefinition(const std::string& protocol) const override; | ||
const bool isSupported(const std::string& protocol) const override; | ||
}; | ||
|
||
}; // namespace net | ||
}; // namespace iggy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#include "address.h" | ||
#include "protocol.h" | ||
|
||
iggy::net::address::LogicalAddress iggy::net::protocol::ProtocolProvider::createAddress(const std::string& url) const { | ||
return iggy::net::address::LogicalAddress(url, this); | ||
} | ||
|
||
const std::string iggy::net::protocol::normalizeProtocolName(const std::string& protocol) { | ||
// convert to lowercase | ||
std::string lowerStr = protocol; | ||
std::transform(lowerStr.begin(), lowerStr.end(), lowerStr.begin(), ::tolower); | ||
|
||
// trim whitespace from the start | ||
auto start = lowerStr.find_first_not_of(" \t\n\r\f\v"); | ||
if (start == std::string::npos) { | ||
throw std::invalid_argument("Protocol name cannot be empty"); | ||
} | ||
|
||
// trim whitespace from the end | ||
auto end = lowerStr.find_last_not_of(" \t\n\r\f\v"); | ||
|
||
// return the trimmed, lowercase string | ||
return lowerStr.substr(start, end - start + 1); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
#include <vector> | ||
#include "transport.h" | ||
|
||
namespace iggy { | ||
namespace net { | ||
namespace address { | ||
class LogicalAddress; | ||
}; | ||
|
||
namespace protocol { | ||
|
||
/** | ||
* @brief Enumerates the supported message encodings. | ||
*/ | ||
enum MessageEncoding { BINARY = 0, TEXT = 1 }; | ||
|
||
/** | ||
* @brief Normalizes the protocol name to a canonical form. | ||
*/ | ||
const std::string normalizeProtocolName(const std::string& protocol); | ||
|
||
|
||
/** | ||
* @brief Metadata about a protocol including its default port, transport, TLS support and message encoding. | ||
*/ | ||
class ProtocolDefinition { | ||
private: | ||
std::string name; | ||
unsigned short defaultPort; | ||
iggy::net::transport::Transport transport; | ||
bool tlsSupported; | ||
MessageEncoding messageEncoding; | ||
|
||
public: | ||
ProtocolDefinition(const std::string& name, | ||
unsigned short defaultPort, | ||
iggy::net::transport::Transport transport, | ||
bool tlsSupported, | ||
MessageEncoding messageEncoding) | ||
: name(iggy::net::protocol::normalizeProtocolName(name)) | ||
, defaultPort(defaultPort) | ||
, transport(transport) | ||
, tlsSupported(tlsSupported) | ||
, messageEncoding(messageEncoding) {} | ||
|
||
ProtocolDefinition() = default; | ||
ProtocolDefinition(const ProtocolDefinition& other) = default; | ||
|
||
const std::string& getName() const { return name; } | ||
unsigned short getDefaultPort() const { return defaultPort; } | ||
iggy::net::transport::Transport getTransport() const { return transport; }; | ||
bool isTlsSupported() const { return tlsSupported; } | ||
MessageEncoding getMessageEncoding() const { return messageEncoding; } | ||
}; | ||
|
||
/** | ||
* @brief Interface to plug in library-specific information on supported protocols. | ||
*/ | ||
class ProtocolProvider { | ||
public: | ||
ProtocolProvider() = default; | ||
virtual ~ProtocolProvider() = default; | ||
|
||
/** | ||
* @brief Factory method to create a logical address from a URL. | ||
*/ | ||
iggy::net::address::LogicalAddress createAddress(const std::string& url) const; | ||
|
||
/** | ||
* @brief Enumerates all the supported protocols in the provider. | ||
*/ | ||
virtual const std::vector<ProtocolDefinition>& getSupportedProtocols() const = 0; | ||
|
||
/** | ||
* @brief Given a normalized protocol name returns the definition with protocol metadata. | ||
*/ | ||
virtual const ProtocolDefinition& getProtocolDefinition(const std::string& protocol) const; | ||
|
||
/** | ||
* @brief Tests whether the given protocol is supported by this provider. | ||
*/ | ||
virtual const bool isSupported(const std::string& protocol) const; | ||
}; | ||
|
||
}; // namespace protocol | ||
}; // namespace net | ||
}; // namespace iggy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#pragma once |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#pragma once |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#pragma once |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#pragma once |
Oops, something went wrong.