Advertisement
masa-

Minecraft server ping (ping.py for the other server scripts)

Aug 16th, 2017
1,360
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.08 KB | None | 0 0
  1. # -*- coding: UTF-8 -*-
  2.  
  3. import socket
  4. import sys
  5.  
  6.  
  7. timeout = 1.7
  8. server_host = "localhost"
  9. server_port = 25565
  10.  
  11. # Minecraft Ping protocol to use:
  12. # 1 = Minecraft Beta 1.8 - Minecraft 1.3
  13. # 2 = Minecraft 1.4 - 1.5
  14. # 3 = Minecraft 1.6
  15. protocol = 1
  16.  
  17. # Parse the command line arguments
  18. # We can have '[host]', '[host] [port]', '[host:port]',
  19. # '[host] [port] [timeout]' or '[host:port] [timeout]'
  20. if len(sys.argv) == 2:
  21.     if ':' in sys.argv[1]:
  22.         tmp = str(sys.argv[1]).split(':')
  23.         server_host = str(tmp[0])
  24.         server_port = int(tmp[1])
  25.     else:
  26.         server_host = str(sys.argv[1])
  27.  
  28. elif len(sys.argv) >= 3:
  29.     if ':' in sys.argv[1]:
  30.         tmp = str(sys.argv[1]).split(':')
  31.         server_host = str(tmp[0])
  32.         server_port = int(tmp[1])
  33.         timeout = float(sys.argv[2])
  34.     else:
  35.         server_host = str(sys.argv[1])
  36.         server_port = int(sys.argv[2])
  37.  
  38.     if len(sys.argv) >= 4:
  39.         timeout = float(sys.argv[3])
  40.         if len(sys.argv) >= 5:
  41.             protocol = int(sys.argv[4])
  42.  
  43.  
  44. #print str('host: {} port: {} timeout: {}').format(server_host, server_port, timeout)
  45. #sys.exit()
  46.  
  47. def ping(host, port, timeout = 1.7, protocol = 1):
  48.     """Ping the server and return the values the server gives us"""
  49.  
  50.     if protocol == 1:
  51.         # Send 0xFE: Server list ping (Minecraft Beta 1.8 - 1.3)
  52.         msg = "\xFE"
  53.         #sock.sendall("\xFE")
  54.     elif protocol == 2:
  55.         # Send 0xFE 0x01: Server list ping (Minecraft 1.4 - 1.5)
  56.         msg = "\xFE\x01"
  57.         #sock.sendall("\xFE\x01")
  58.     elif protocol == 3:
  59.         # Server list ping (Minecraft 1.6)
  60.         msg = "\xFE\x01\xFA"
  61.         msg += "\x00\x0B" # The length of the following string, in characters, as a short (always 11)
  62.  
  63.         # "MC|PingHost" encoded as a big-endian UCS-2 string:
  64.         msg += "\x00\x4D\x00\x43\x00\x7C\x00\x50\x00\x69\x00\x6E\x00\x67\x00\x48\x00\x6F\x00\x73\x00\x74"
  65.  
  66.         # FIXME/TODO:
  67.         # Alternatively:
  68.         #msg += str('MC|PingHost').encode('UTF-16BE')
  69.  
  70.         #msg += "" # The length of the rest of the data, as a short. Compute as 7 + 2 * strlen(hostname)
  71.         #msg += "" # Protocol version, currently 74 (decimal)
  72.         #msg += "" # The length of following string, in characters, as a short
  73.         #msg += "" # The hostname the client is connecting to, encoded in the same way as "MC|PingHost"
  74.         #msg += "" # The port the client is connecting to, as an int
  75.     else:
  76.         print(str('ping(): Error, invalid protocol: {}').format(protocol))
  77.         return None
  78.  
  79.     try:
  80.         #sock = socket.create_connection((server_address, server_port), timeout)
  81.         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  82.     except socket.error as msg:
  83.         #print('socket(): except:', msg)
  84.         sock = None
  85.         return None
  86.  
  87.     try:
  88.         #sock.setblocking(0)
  89.         sock.settimeout(timeout)
  90.         sock.connect((host, port))
  91.     except socket.error as msg:
  92.         #print('connect(): except:', msg)
  93.         sock = None
  94.         return None
  95.  
  96.     sock.sendall(msg)
  97.  
  98.     try:
  99.         val = sock.recv(256)
  100.     except socket.error as msg:
  101.         sock.close()
  102.         #print('recv(): except:', msg)
  103.         return None
  104.  
  105.     sock.shutdown(socket.SHUT_RDWR)
  106.     sock.close()
  107.  
  108.     # Check for a valid 0xFF disconnect
  109.     if val[0] != "\xFF":
  110.         return None
  111.  
  112.     if protocol == 1:
  113.         # Remove the packet ident (0xFF) and the short containing the length of the string
  114.         # Minecraft Beta 1.8 - 1.3
  115.         val = val[3:]
  116.     elif protocol == 2 or protocol == 3:
  117.         # Remove the packet ident (0xFF) and the short containing the length of the string
  118.         # and the rest of the crap
  119.         # Minecraft 1.4 - 1.5, 1.6
  120.         val = val[9:]
  121.  
  122.     # Decode UCS-2 string
  123.     #val = val.decode('UTF-16LE')
  124.     val = val.decode('UTF-16BE')
  125.  
  126.     if protocol == 1:
  127.         # Split into a list (Minecraft Beta 1.8 - 1.3)
  128.         val = val.split(u"\xA7")
  129.     elif protocol == 2 or protocol == 3:
  130.         # Split into a list (Minecraft 1.4 - 1.5, 1.6)
  131.         val = val.split("\x00")
  132.  
  133.     # Debug:
  134.     #print('Length of val:', len(val))
  135.     #print(val)
  136.     #return "foo"
  137.  
  138.     #if len(val) < 3:
  139.     #   return None
  140.  
  141.     if len(val) == 3:
  142.         # Return a dictionary of values (Minecraft Beta 1.8 - 1.3)
  143.         # values: MOTD, num_player, max_players
  144.         return {'motd': val[0],\
  145.             'num_players': int(val[1]),\
  146.             'max_players': int(val[2])}
  147.     elif len(val) == 5:
  148.         # Return a dictionary of values (Minecraft 1.4 - 1.5, 1.6)
  149.         # values: protocol_version, version, MOTD, num_player, max_players
  150.         return {'protocol_version': int(val[0]),\
  151.             'version': val[1],\
  152.             'motd': val[2],\
  153.             'num_players': int(val[3]),\
  154.             'max_players': int(val[4])}
  155.     else:
  156.         return None
  157.  
  158.  
  159.  
  160.  
  161.  
  162. def check_server(host, port, timeout = 1.7, protocol = 1):
  163.     """Check if the server is up by ping()ing it checking for the known keys"""
  164.  
  165.     data = ping(host, port, timeout, protocol)
  166.     #print('host:', host, 'port:', port, data)
  167.  
  168.     if type(data) is dict:
  169.         if 'version' in data:
  170.             msg = str('{}:{} ([{}], {}): OK').format(host, port, data['version'], data['motd'])
  171.             print msg          
  172.         elif 'motd' in data:
  173.             msg = str('{}:{} ({}): OK').format(host, port, data['motd'])
  174.             print msg
  175.             #print '%s: up' % data['motd']
  176.         else:
  177.             msg = str('{}:{}: N/A').format(host, port)
  178.             print msg
  179.             #print '%s: down' % data['motd']
  180.     else:
  181.         msg = str('{}:{}: N/A').format(host, port)
  182.         print msg
  183.  
  184.     return None
  185.  
  186.  
  187. check_server(server_host, server_port, timeout, protocol)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement