2024-10-29 02:05:56 +00:00
|
|
|
/**
|
|
|
|
* Defines various address types for use with HTTP communication.
|
|
|
|
*/
|
|
|
|
module handy_http_primitives.address;
|
|
|
|
|
2024-10-30 12:08:43 +00:00
|
|
|
/**
|
|
|
|
* Represents a 4-byte IPv4 network address and the port number on this machine
|
|
|
|
* that the connection was assigned to.
|
|
|
|
*/
|
2024-10-29 02:05:56 +00:00
|
|
|
struct IPv4InternetAddress {
|
|
|
|
const ubyte[4] bytes;
|
|
|
|
const ushort port;
|
|
|
|
|
|
|
|
string toString() const {
|
|
|
|
char[21] buffer;
|
|
|
|
size_t idx;
|
|
|
|
for (size_t i = 0; i < 4; i++) {
|
|
|
|
writeUIntToBuffer(bytes[i], buffer, idx);
|
|
|
|
if (i < 3) buffer[idx++] = '.';
|
|
|
|
}
|
|
|
|
buffer[idx++] = ':';
|
|
|
|
writeUIntToBuffer(port, buffer, idx);
|
|
|
|
return buffer[0 .. idx].idup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-30 12:08:43 +00:00
|
|
|
/**
|
|
|
|
* Represents a 16-byte IPv6 network address and the port number on this
|
|
|
|
* machine that the connection was assigned to.
|
|
|
|
*/
|
2024-10-29 02:05:56 +00:00
|
|
|
struct IPv6InternetAddress {
|
|
|
|
const ubyte[16] bytes;
|
|
|
|
const ushort port;
|
|
|
|
|
|
|
|
string toString() const {
|
|
|
|
return "Not implemented!";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-30 12:08:43 +00:00
|
|
|
/**
|
|
|
|
* Represents a unix socket address, which is just a path to a file at which
|
|
|
|
* IO operations take place.
|
|
|
|
*/
|
2024-10-29 02:05:56 +00:00
|
|
|
struct UnixSocketAddress {
|
|
|
|
const string path;
|
|
|
|
|
|
|
|
string toString() const {
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-30 12:08:43 +00:00
|
|
|
/// Defines the different possible address types, used by `ClientAddress`.
|
2024-10-29 02:05:56 +00:00
|
|
|
enum ClientAddressType {
|
|
|
|
IPv4,
|
|
|
|
IPv6,
|
|
|
|
UNIX
|
|
|
|
}
|
|
|
|
|
2024-10-30 12:08:43 +00:00
|
|
|
/**
|
|
|
|
* A compound type representing the address of any entity sending an HTTP
|
|
|
|
* request. Use `type` to determine which information is available.
|
|
|
|
*/
|
2024-10-29 02:05:56 +00:00
|
|
|
struct ClientAddress {
|
|
|
|
const ClientAddressType type;
|
|
|
|
const IPv4InternetAddress ipv4InternetAddress;
|
|
|
|
const IPv6InternetAddress ipv6InternetAddress;
|
|
|
|
const UnixSocketAddress unixSocketAddress;
|
|
|
|
|
|
|
|
string toString() const {
|
|
|
|
if (type == ClientAddressType.IPv4) {
|
|
|
|
return ipv4InternetAddress.toString();
|
|
|
|
} else if (type == ClientAddressType.IPv6) {
|
|
|
|
return ipv6InternetAddress.toString();
|
|
|
|
} else {
|
|
|
|
return unixSocketAddress.toString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static ClientAddress ofIPv4(IPv4InternetAddress addr) {
|
|
|
|
return ClientAddress(ClientAddressType.IPv4, addr, IPv6InternetAddress.init, UnixSocketAddress.init);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ClientAddress ofIPv6(IPv6InternetAddress addr) {
|
|
|
|
return ClientAddress(ClientAddressType.IPv6, IPv4InternetAddress.init, addr, UnixSocketAddress.init);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ClientAddress ofUnixSocket(UnixSocketAddress addr) {
|
|
|
|
return ClientAddress(ClientAddressType.UNIX, IPv4InternetAddress.init, IPv6InternetAddress.init, addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unittest {
|
|
|
|
ClientAddress addr = ClientAddress.ofIPv4(IPv4InternetAddress([127, 0, 0, 1], 8000));
|
|
|
|
assert(addr.toString == "127.0.0.1:8000");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper function to append an unsigned integer value to a char buffer. It is
|
|
|
|
* assumed that there's enough space to write value.
|
|
|
|
* Params:
|
|
|
|
* value = The value to append.
|
|
|
|
* buffer = The buffer to append to.
|
|
|
|
* idx = A reference to a variable tracking the next writable index in the buffer.
|
|
|
|
*/
|
|
|
|
private void writeUIntToBuffer(uint value, char[] buffer, ref size_t idx) {
|
|
|
|
const size_t startIdx = idx;
|
|
|
|
while (true) {
|
|
|
|
ubyte remainder = value % 10;
|
|
|
|
value /= 10;
|
|
|
|
buffer[idx++] = cast(char) ('0' + remainder);
|
|
|
|
if (value == 0) break;
|
|
|
|
}
|
|
|
|
// Swap the characters to proper order.
|
|
|
|
for (size_t i = 0; i < (idx - startIdx) / 2; i++) {
|
|
|
|
size_t p1 = i + startIdx;
|
|
|
|
size_t p2 = idx - i - 1;
|
|
|
|
char tmp = buffer[p1];
|
|
|
|
buffer[p1] = buffer[p2];
|
|
|
|
buffer[p2] = tmp;
|
|
|
|
}
|
|
|
|
}
|