diff options
Diffstat (limited to 'doc/protocol.md')
-rw-r--r-- | doc/protocol.md | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/doc/protocol.md b/doc/protocol.md new file mode 100644 index 000000000..4c8ddd500 --- /dev/null +++ b/doc/protocol.md @@ -0,0 +1,110 @@ +Minetest protocol (incomplete, early draft): +Updated 2011-06-18 + +A custom protocol over UDP. +Integers are big endian. +Refer to connection.{h,cpp} for further reference. + +Initialization: +- A dummy reliable packet with peer_id=PEER_ID_INEXISTENT=0 is sent to the server: + - Actually this can be sent without the reliable packet header, too, i guess, + but the sequence number in the header allows the sender to re-send the + packet without accidentally getting a double initialization. + - Packet content: + # Basic header + u32 protocol_id = PROTOCOL_ID = 0x4f457403 + u16 sender_peer_id = PEER_ID_INEXISTENT = 0 + u8 channel = 0 + # Reliable packet header + u8 type = TYPE_RELIABLE = 3 + u16 seqnum = SEQNUM_INITIAL = 65500 + # Original packet header + u8 type = TYPE_ORIGINAL = 1 + # And no actual payload. +- Server responds with something like this: + - Packet content: + # Basic header + u32 protocol_id = PROTOCOL_ID = 0x4f457403 + u16 sender_peer_id = PEER_ID_INEXISTENT = 0 + u8 channel = 0 + # Reliable packet header + u8 type = TYPE_RELIABLE = 3 + u16 seqnum = SEQNUM_INITIAL = 65500 + # Control packet header + u8 type = TYPE_CONTROL = 0 + u8 controltype = CONTROLTYPE_SET_PEER_ID = 1 + u16 peer_id_new = assigned peer id to client (other than 0 or 1) +- Then the connection can be disconnected by sending: + - Packet content: + # Basic header + u32 protocol_id = PROTOCOL_ID = 0x4f457403 + u16 sender_peer_id = whatever was gotten in CONTROLTYPE_SET_PEER_ID + u8 channel = 0 + # Control packet header + u8 type = TYPE_CONTROL = 0 + u8 controltype = CONTROLTYPE_DISCO = 3 + +- Here's a quick untested connect-disconnect done in PHP: +# host: ip of server (use gethostbyname(hostname) to get from a dns name) +# port: port of server +function check_if_minetestserver_up($host, $port) +{ + $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + $timeout = array("sec" => 1, "usec" => 0); + socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, $timeout); + $buf = "\x4f\x45\x74\x03\x00\x00\x00\x03\xff\xdc\x01"; + socket_sendto($socket, $buf, strlen($buf), 0, $host, $port); + $buf = socket_read($socket, 1000); + if($buf != "") + { + # We got a reply! read the peer id from it. + $peer_id = substr($buf, 9, 2); + + # Disconnect + $buf = "\x4f\x45\x74\x03".$peer_id."\x00\x00\x03"; + socket_sendto($socket, $buf, strlen($buf), 0, $host, $port); + socket_close($socket); + + return true; + } + return false; +} + +- Here's a Python script for checking if a minetest server is up, confirmed working + +#!/usr/bin/env python3 +import sys, time, socket + +address = "" +port = 30000 +if len(sys.argv) <= 1: + print("Usage: %s <address>" % sys.argv[0]) + exit() +if ":" in sys.argv[1]: + address = sys.argv[1].split(":")[0] + try: + port = int(sys.argv[1].split(":")[1]) + except ValueError: + print("Please specify a valid port") + exit() +else: + address = sys.argv[1] + +try: + start = time.time() + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.settimeout(2.0) + buf = b"\x4f\x45\x74\x03\x00\x00\x00\x01" + sock.sendto(buf, (address, port)) + data, addr = sock.recvfrom(1000) + if data: + peer_id = data[12:14] + buf = b"\x4f\x45\x74\x03" + peer_id + b"\x00\x00\x03" + sock.sendto(buf, (address, port)) + sock.close() + end = time.time() + print("%s is up (%0.5fms)" % (sys.argv[1], end - start)) + else: + print("%s seems to be down " % sys.argv[1]) +except Exception as err: + print("%s seems to be down (%s) " % (sys.argv[1], str(err))) |