Skip to content

Instantly share code, notes, and snippets.

@erde74
Created May 16, 2016 09:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erde74/5bd7d91070791142c929258fee8d887b to your computer and use it in GitHub Desktop.
Save erde74/5bd7d91070791142c929258fee8d887b to your computer and use it in GitHub Desktop.
module multiaddr.protocols;
import std.algorithm;
import std.bitmanip;
import std.conv;
import std.format;
import std.string;
import std.typecons;
// Protocol is a Multiaddr protocol description structure.
struct Protocol {
int Code;
int Size; // a size of -1 indicates a length-prefixed variable size
string Name;
byte[] VCode;
}
// replicating table here to:
// 1. avoid parsing the csv
// 2. ensuring errors in the csv don't screw up code.
// 3. changing a number has to happen in two places.
enum P_IP4 = 4;
enum P_TCP = 6;
enum P_UDP = 17;
enum P_DCCP = 33;
enum P_IP6 = 41;
enum P_SCTP = 132;
enum P_UTP = 301;
enum P_UDT = 302;
enum P_IPFS = 421;
enum P_HTTP = 480;
enum P_HTTPS = 443;
enum P_ONION = 444;
// These are special sizes
enum LengthPrefixedVarSize = -1;
// Protocols is the list of multiaddr protocols supported by this module.
Protocol[] Protocols = [
{P_IP4, 32, "ip4", CodeToVarint(P_IP4)},
{P_TCP, 16, "tcp", CodeToVarint(P_TCP)},
{P_UDP, 16, "udp", CodeToVarint(P_UDP)},
{P_DCCP, 16, "dccp", CodeToVarint(P_DCCP)},
{P_IP6, 128, "ip6", CodeToVarint(P_IP6)},
// these require varint:
{P_SCTP, 16, "sctp", CodeToVarint(P_SCTP)},
{P_ONION, 80, "onion", CodeToVarint(P_ONION)},
{P_UTP, 0, "utp", CodeToVarint(P_UTP)},
{P_UDT, 0, "udt", CodeToVarint(P_UDT)},
{P_HTTP, 0, "http", CodeToVarint(P_HTTP)},
{P_HTTPS, 0, "https", CodeToVarint(P_HTTPS)},
{P_IPFS, LengthPrefixedVarSize, "ipfs", CodeToVarint(P_IPFS)},
];
string AddProtocol(Protocol p) {
foreach (pt; Protocols) {
if (pt.Code == p.Code) {
return format("protocol code %d already taken by %s", p.Code, pt.Name);
}
if (pt.Name == p.Name) {
return format("protocol by the name %s already exists", p.Name);
}
}
Protocols ~= p;
return null;
}
// ProtocolWithName returns the Protocol description with given string name.
Protocol ProtocolWithName(string s) {
foreach (p; Protocols) {
if (p.Name == s) {
return p;
}
}
return Protocol();
}
// ProtocolWithCode returns the Protocol description with given protocol code.
Protocol ProtocolWithCode(int c) {
foreach (p; Protocols) {
if (p.Code == c) {
return p;
}
}
return Protocol();
}
// ProtocolsWithString returns a slice of protocols matching given string.
auto ProtocolsWithString(string s) {
s = strip(s, '/');
auto sp = split(s, "/");
if (sp.length == 0) {
return tuple(new Protocol[0], "");
}
auto t = new Protocol[sp.length];
foreach (i, name; sp) {
auto p = ProtocolWithName(name);
if (p.Code == 0) {
return tuple(new Protocol[0], format("no protocol with name: %s", name));
}
t[i] = p;
}
return tuple(t, "");
}
// CodeToVarint converts an integer to a varint-encoded byte[]
auto CodeToVarint(int num) {
byte[long.sizeof] buf = new byte[long.sizeof];
version(LittleEndian) {
byte[num.sizeof] b = cast(byte[])nativeToLittleEndian(num);
}
else {
byte[num.sizeof] b = cast(byte[])nativeToBigEndian(num);
}
buf[0 .. num.sizeof] = b[0 .. $];
return buf;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment