FediChordProtocol DEFINITIONS AUTOMATIC TAGS ::= BEGIN NodeID ::= INTEGER (0..115792089237316195423570985008687907853269984665640564039457584007913129639935) Domain ::= VisibleString Partnum ::= INTEGER (0..150) Action ::= ENUMERATED {queryID, join, leave, stabilise, ping, queryLoad} Request ::= SEQUENCE { action Action, requestID INTEGER (0..4294967295), -- arbitrarily restricting to an unsigned 32bit integer sender NodeState, part Partnum, -- part number of this message, starts at 1 finalPart BOOLEAN, -- flag indicating this `part` to be the last of this reuest actionPayload CHOICE { queryIDRequestPayload QueryIDRequestPayload, joinRequestPayload JoinRequestPayload, leaveRequestPayload LeaveRequestPayload, stabiliseRequestPayload StabiliseRequestPayload, pingRequestPayload PingRequestPayload, loadRequestPayload LoadRequestPayload } OPTIONAL -- just for symmetry reasons with response, requests without a payload have no meaning } -- idea: different message layouts as a way of distinguishing between -- request and response instead of explicit flag Response ::= SEQUENCE { -- requestID of the request responding to requestID INTEGER (0..4294967295), -- arbitrarily restricting to an unsigned 32bit integer senderID NodeID, part Partnum, finalPart BOOLEAN, -- flag indicating this `part` to be the last of this response action Action, actionPayload CHOICE { queryIDResponsePayload QueryIDResponsePayload, joinResponsePayload JoinResponsePayload, leaveResponsePayload LeaveResponsePayload, stabiliseResponsePayload StabiliseResponsePayload, pingResponsePayload PingResponsePayload, loadResponsePayload LoadResponsePayload } OPTIONAL -- no payload when just ACKing a previous request } NodeState ::= SEQUENCE { nid NodeID, domain Domain, ipAddr OCTET STRING (SIZE(16)), dhtPort INTEGER, servicePort INTEGER, vServerID INTEGER (0..255) } CacheEntry ::= SEQUENCE { node NodeState, -- use POSIX time stamp, as DATE-TIME isn't supported by the Haskell lib timestamp INTEGER } NodeCache ::= SEQUENCE OF CacheEntry JoinRequestPayload ::= NULL JoinResponsePayload ::= SEQUENCE { successors SEQUENCE OF NodeState, predecessors SEQUENCE OF NodeState, cache NodeCache } QueryResult ::= ENUMERATED { found, forward } QueryIDRequestPayload ::= SEQUENCE { targetID NodeID, lBestNodes INTEGER } QueryIDResponsePayload ::= SEQUENCE { result QueryResult, nodeData CHOICE {NodeState, NodeCache} } StabiliseRequestPayload ::= NULL StabiliseResponsePayload ::= SEQUENCE { successors SEQUENCE OF NodeState, predecessors SEQUENCE OF NodeState -- ToDo: transfer of handled key data, if newly responsible for it } LeaveRequestPayload ::= SEQUENCE { successors SEQUENCE OF NodeState, predecessors SEQUENCE OF NodeState, doMigration BOOLEAN } LeaveResponsePayload ::= NULL -- just a confirmation PingRequestPayload ::= NULL -- do not include a node/ vserver ID, so that -- the node has to respond with all active ones -- learning all active vserver IDs handled by the server at once PingResponsePayload ::= SEQUENCE OF NodeState LoadRequestPayload ::= SEQUENCE { lowerBound NodeID, upperBound NodeID } LoadResponsePayload ::= SEQUENCE { loadSum REAL, remainingLoadTarget REAL } END