Browse Source

big new class to process serverinfos in hash

Paul Klumpp 11 years ago
parent
commit
20fb7cb0b9
1 changed files with 606 additions and 113 deletions
  1. 606 113
      em_server.rb

+ 606 - 113
em_server.rb

@@ -5,13 +5,15 @@ require 'digest/md5'
 require 'fiber'
 require 'geoip'
 require 'socket'
+require 'timeout'
+
 
 
 
 # .. allowed commands .. ROLES = CAPABILITIES
 # normal users have ROLE broadcast. Roles are defined on a per-user basis .. in a config.
 
-$version = "0.2EventMachineSocketServer"
+$version = "0.4em_cooldns_classes_for_caching"
 $debug = 0
 
 $role_commands = Hash[
@@ -22,7 +24,7 @@ $role_commands = Hash[
   'broadcast' => %w(REQ_BC BC_RE),
 	
 	'specbot_admin' => %w(REQ_ASSIGN REQ_UNASSIGN REQ_PING REQ_ASSIGNMENTS),
-	'specbot' => %w(ASSIGN_RE UNASSIGN_RE PING_RE ASSIGNMENTS_RE),
+	'specbot' => %w(ASSIGN_RE UNASSIGN_RE PING_RE ASSIGNMENTS_RE REQ_DNS),
 ]
 
 $default_role = "everyone"
@@ -57,7 +59,564 @@ $user_roles = Hash[
 	'central_brain' => %w(everyone broadcast_admin specbot_admin),
 ]
 
-$qw_server = Hash.new
+
+$qw_list = Array.new
+$qw_list = [
+    "89.149.194.72:27700",
+        "84.200.47.113:30000",
+        "89.149.194.72:27500",
+        "84.200.47.113:28502",
+        "89.149.194.72:30000",
+        "89.149.194.72:27600",
+        "93.186.192.16:28502",
+        "84.200.47.113:28501",
+        "93.186.192.16:28501",
+        "188.40.130.10:27502",
+        "93.186.192.16:30000",
+        "188.40.130.10:27599",
+        "188.40.130.10:27503",
+        "194.109.69.75:28000",
+        "194.109.69.75:27500",
+        "194.109.69.75:27501",
+        "194.109.69.76:28504",
+        "188.165.243.56:30000",
+        "188.40.130.10:27501",
+        "194.109.69.76:28502",
+        "194.109.69.76:28501",
+        "194.109.69.76:28503",
+        "62.24.64.11:27501",
+        "62.24.64.11:44444",
+        "188.40.103.81:27600",
+        "62.24.64.11:30000",
+        "194.109.69.75:27502",
+        "91.121.69.201:30000",
+        "37.59.63.97:28504",
+        "188.40.130.10:27500",
+        "188.165.243.56:28009",
+        "37.59.63.97:28501",
+        "62.24.64.11:27500",
+        "37.59.63.97:28503",
+        "194.109.69.76:30000",
+        "188.165.243.56:28008",
+        "188.165.243.56:28006",
+        "188.165.243.56:28001",
+        "188.165.243.56:28002",
+        "93.186.192.16:27500",
+        "91.121.69.201:27600",
+        "37.59.63.97:28502",
+        "91.121.223.163:28001",
+        "188.165.243.56:28003",
+        "109.74.195.224:30000",
+        "178.79.183.178:27500",
+        "77.74.194.189:27501",
+        "91.121.69.201:27502",
+        "188.165.243.56:28007",
+        "109.74.195.224:27500",
+        "213.5.176.135:27502",
+        "77.74.194.189:27504",
+        "178.79.172.251:27600",
+        "77.74.194.189:27502",
+        "77.74.194.189:27503",
+        "213.5.176.135:27500",
+        "109.74.195.224:27501",
+        "89.104.194.146:27504",
+        "89.104.194.146:27503",
+        "89.104.194.146:27508",
+        "213.5.176.136:27510",
+        "213.5.176.135:27501",
+        "213.5.176.135:27503",
+        "77.74.194.189:30000",
+        "89.149.194.72:27800",
+        "89.104.194.146:27502",
+        "89.104.194.146:27666",
+        "89.104.194.146:27507",
+        "89.104.194.146:27509",
+        "89.104.194.146:30000",
+        "188.165.243.56:28004",
+        "89.104.194.146:27500",
+        "89.104.194.146:27501",
+        "194.109.69.76:27500",
+        "89.104.194.146:27506",
+        "94.236.92.49:27501",
+        "91.121.69.201:27501",
+        "213.239.214.134:27500",
+        "89.104.194.146:27510",
+        "95.131.48.86:27502",
+        "94.236.92.49:27500",
+        "94.236.92.49:30000",
+        "95.131.48.86:27504",
+        "78.137.161.109:27501",
+        "188.165.243.56:28005",
+        "178.217.185.104:27500",
+        "178.217.185.104:27600",
+        "178.217.185.104:30000",
+        "87.102.202.23:27502",
+        "78.137.161.109:27500",
+        "89.104.194.146:27505",
+        "87.102.202.23:27505",
+        "178.217.185.104:27501",
+        "91.121.69.201:27500",
+        "82.141.152.3:27501",
+        "82.141.152.3:27500",
+        "83.179.23.16:28002",
+        "109.74.7.60:27500",
+        "212.62.234.153:27502",
+        "83.179.23.16:28003",
+        "195.54.182.34:27500",
+        "83.179.23.16:28005",
+        "212.62.234.153:27503",
+        "95.143.243.24:27600",
+        "83.179.23.16:28001",
+        "212.62.234.153:27504",
+        "78.137.161.109:27502",
+        "83.179.23.16:28004",
+        "212.62.234.153:27501",
+        "95.143.243.24:27500",
+        "109.228.137.161:28501",
+        "95.143.243.24:27900",
+        "83.226.149.218:27500",
+        "83.226.149.218:28001",
+        "83.226.149.218:28002",
+        "83.226.149.218:28003",
+        "193.1.40.166:27975",
+        "87.237.112.11:30000",
+        "217.30.184.104:27500",
+        "78.108.53.19:27500",
+        "78.108.53.19:27501",
+        "195.54.142.7:28001",
+        "193.1.40.166:27500",
+        "87.237.112.11:27501",
+        "195.54.142.7:30000",
+        "195.54.142.7:28007",
+        "217.119.36.79:30000",
+        "95.131.48.86:27501",
+        "195.54.142.7:28002",
+        "195.54.142.7:28008",
+        "80.101.105.103:27500",
+        "87.237.112.11:27502",
+        "217.119.36.79:27500",
+        "81.170.128.75:28501",
+        "217.119.36.79:28001",
+        "193.1.40.167:27500",
+        "217.119.36.79:28003",
+        "217.119.36.79:28002",
+        "81.170.128.75:30000",
+        "81.170.128.75:28504",
+        "195.54.142.7:28005",
+        "195.54.142.7:28010",
+        "81.170.128.75:28503",
+        "93.81.254.63:27502",
+        "212.42.38.88:27504",
+        "81.170.128.75:28502",
+        "93.81.254.63:27500",
+        "81.170.128.75:28000",
+        "212.42.38.88:27500",
+        "82.203.213.117:28002",
+        "212.42.38.88:30000",
+        "93.81.254.63:30000",
+        "82.203.213.117:28001",
+        "212.42.38.88:27501",
+        "212.42.38.88:27503",
+        "93.81.254.63:27503",
+        "93.81.254.63:27501",
+        "82.203.213.117:30000",
+        "95.131.48.86:27503",
+        "83.252.244.76:27500",
+        "212.42.38.88:27502",
+        "195.54.142.7:28003",
+        "95.31.4.132:30000",
+        "83.252.244.76:27501",
+        "93.81.254.63:30001",
+        "195.54.142.7:28006",
+        "82.203.213.117:28003",
+        "95.143.243.24:27700",
+        "84.234.185.215:27503",
+        "84.234.185.215:27500",
+        "84.234.185.215:27519",
+        "84.234.185.215:27508",
+        "84.234.185.215:27506",
+        "84.234.185.215:27505",
+        "195.54.142.7:28004",
+        "84.234.185.215:27501",
+        "195.54.142.7:28009",
+        "212.109.128.148:27501",
+        "84.234.185.215:27502",
+        "31.209.7.104:28501",
+        "194.79.85.66:27501",
+        "194.79.85.66:30000",
+        "95.84.164.245:27501",
+        "194.79.85.66:27502",
+        "83.222.112.157:30000",
+        "212.109.128.148:27500",
+        "94.100.6.66:27500",
+        "129.241.205.153:28000",
+        "84.234.185.215:27507",
+        "129.241.205.153:27500",
+        "95.84.164.245:27500",
+        "69.31.82.226:27501",
+        "69.31.82.226:30000",
+        "130.240.207.177:30000",
+        "69.31.82.226:28100",
+        "69.31.82.226:27500",
+        "69.31.82.226:28101",
+        "69.31.82.226:28010",
+        "69.31.82.226:30001",
+        "69.31.82.226:28000",
+        "69.31.82.226:28002",
+        "93.186.192.16:28000",
+        "195.222.130.83:27500",
+        "84.200.47.113:28000",
+        "130.85.56.131:27500",
+        "108.174.51.73:28003",
+        "96.8.113.36:27501",
+        "96.8.113.36:27500",
+        "68.100.130.114:27501",
+        "65.31.69.75:27500",
+        "108.174.51.73:28006",
+        "65.31.69.75:27508",
+        "108.174.51.73:30000",
+        "67.81.59.41:27500",
+        "108.174.51.73:28004",
+        "217.18.138.23:27505",
+        "108.174.51.73:28001",
+        "68.100.130.114:27500",
+        "174.49.198.60:27502",
+        "174.49.198.60:27503",
+        "209.239.113.236:27500",
+        "174.49.198.60:27515",
+        "217.119.36.79:28000",
+        "108.174.51.73:28005",
+        "74.91.115.244:28001",
+        "174.49.198.60:27500",
+        "74.91.115.244:28000",
+        "199.101.96.48:27501",
+        "96.8.113.36:30000",
+        "174.101.185.59:27500",
+        "67.228.69.114:27502",
+        "199.101.96.48:27500",
+        "108.174.51.73:28002",
+        "199.192.229.74:28001",
+        "74.86.171.201:27502",
+        "67.228.69.114:27501",
+        "74.86.171.201:27500",
+        "67.228.69.114:26666",
+        "199.192.228.71:27501",
+        "199.192.229.74:28003",
+        "74.86.171.201:27501",
+        "199.192.229.74:30000",
+        "199.192.229.74:28002",
+        "74.91.115.244:28002",
+        "199.192.228.71:27500",
+        "199.101.96.48:30000",
+        "199.101.96.48:28000",
+        "199.192.229.74:28004",
+        "199.192.228.71:30000",
+        "65.31.238.37:27500",
+        "31.209.7.104:28000",
+        "208.131.136.169:27500",
+        "66.212.17.78:27500",
+        "200.177.229.11:27510",
+        "200.177.229.11:27522",
+        "200.177.229.11:27521",
+        "200.177.229.11:27500",
+        "190.96.80.67:27500",
+        "200.177.229.11:27511",
+        "200.177.229.11:27520",
+        "190.96.80.67:27000",
+        "202.37.129.186:27500",
+        "202.37.129.186:27505",
+        "202.37.129.186:27501",
+        "219.88.241.81:27500",
+        "202.172.99.2:28001",
+        "202.172.99.2:28002",
+        "202.172.99.2:28003",
+        "202.172.99.2:27500",
+        "210.50.4.11:27501",
+        "202.172.99.2:27501",
+        "210.50.4.11:27508",
+        "210.50.4.11:27511",
+        "210.50.4.11:27509",
+        "210.50.4.11:27510",
+        "122.99.118.2:28001",
+        "210.50.4.11:27500",
+        "210.50.4.11:27503",
+        "210.50.4.11:27506",
+        "210.50.4.11:27505",
+        "210.50.4.11:27504",
+        ]
+
+
+class GameServers
+
+  attr_accessor :gameservers # now, @gameservers is accessible via GameServers.gameservers
+
+  def initialize
+
+    @gameservers = Hash.new
+    @gameservers.default = {
+      :reverse_dns => "",
+      :hostname_dns => "",
+      :cool_dns => "",
+      :type => "",
+      :serverinfos => "",
+      :timestamp => 0,
+    }
+
+    @gameservers["blah:blah"]
+
+    wat = Hash.new(@gameservers["blah:blah"])
+    wat
+    wat.store(:reverse_dns, "6")
+    @gameservers.merge(wat)
+
+    p @gameservers
+    p @gameservers.default
+
+    wat = Hash.new(@gameservers["blah:blah"])
+    wat
+    wat.store(:hostname_dns, "12")
+    @gameservers.merge(wat)
+
+    p @gameservers
+    p @gameservers.default
+
+
+
+  end
+
+  def scanserver(iphostport, type="qw", force=false)
+    put_log "scanserver drin"
+    if iphostport =~ /^(\d+\.\d+\.\d+\.\d+):(\d{1,5})/
+      iphost = $1
+      ipport = $2
+
+      if type == "qw"
+        #p current
+
+        # check if it already exists
+
+        #if @gameservers["#{iphost}:#{ipport}"][:timestamp] > 0
+
+          # if old general data, then freshly get general data...
+        #  if @gameservers["#{iphost}:#{ipport}"][:timestamp] + 60 * 60 * 20 < Time.now.utc.to_i || force == true
+        #  end     # of old
+
+
+        #else
+          current = Hash.new
+
+          serverinfos = qwstatus(iphost, ipport)
+
+          current.store(:serverinfos, serverinfos)
+          current.store(:reverse_dns, find_reverse_dname(iphost))
+          current.store(:hostname_dns, qw_find_dname_by_serverinfos(serverinfos))
+          current.store(:type, "qw")
+          # set new timestamp
+          current.store(:timestamp, Time.now.utc.to_i)
+          @gameservers.store("#{iphost}:#{ipport}", current) # save it all.
+
+          current.store(:cool_dns, find_cooldns(iphost, ipport))
+          @gameservers.store("#{iphost}:#{ipport}", current) # save it all.
+
+          #put_log "the saved one: #{@gameservers.fetch("#{iphost}:#{ipport}").fetch(:cool_dns)}"
+
+          #puts "ALL"
+          #p @gameservers
+          #puts "DEFAULT of the hash"
+          #p @gameservers.default
+
+        #end
+      end # of type qw
+    end # of check form of iphostport parameter
+  end # of scan()
+
+  def scanserverlist(gs_array, type="qw")
+    put_log "scanserverlist drin"
+    gs_array.each do
+      |gserver|
+      scanserver(gserver, type)
+    end
+    put_log "End of scanning."
+    put_log "foppa: #{@gameservers.fetch("89.104.194.146:27503")} "
+  end # of scanserverlist()
+
+  def get_cool_dns(iphost, ipport)
+    put_log "get_cool_dns drin"
+    @gameservers.fetch("#{iphost}:#{ipport}").fetch(:cool_dns)
+  rescue
+    scanserver("#{iphost}:#{ipport}", "qw")
+    @gameservers.fetch("#{iphost}:#{ipport}").fetch(:cool_dns)
+  end
+
+  private # all following methods are private
+  # returns serverinfo hash
+  def qwstatus(iphost, ipport)
+    put_log "qwstatus drin"
+    udp_payload = [0xFF, 0xFF, 0xFF, 0xFF]
+    udp_payload.concat(string2bytearray("status 23"))
+    udp_payload.concat([0x0a]) # linefeed at the end
+
+    udp_payload = udp_payload.pack("C*")
+    #p udp_payload
+
+    Timeout::timeout(2) do
+      begin
+        u2 = UDPSocket.new
+        #put_log "#{iphost} #{ipport} #{udp_payload}"
+        u2.send(udp_payload, 0, iphost, ipport)
+        #put_log "sent"
+
+        the_return = u2.recv(500)
+
+        u2.close
+
+        #put_log "muh #{the_return}"
+        if the_return =~ /\W\W\W\Wn\\(.+)$/
+          line = $1
+          #put_log "line #{line}"
+          matches = line.scan(/(.+?)\\(.+?)(\\|$)/)
+
+          the_hash = Hash.new
+          matches.each {
+              |k, v, _|
+            the_hash[k] = "#{v}"
+          }
+          return the_hash
+        else
+          return false
+        end
+
+      rescue Exception => e
+        puts e.message
+      end # of begin
+    end # of Timeout
+
+
+  end
+
+  def find_cooldns_full(iphost, ipport)
+    targetname = iphost
+    # resolve it to a dns name (reverse lookup)
+    if targetname == iphost # if it is still default
+      put_log "Ip not resolved .. we try hostname dns finder"
+      targetname = qw_find_dname_in_hostnames(iphost, ipport)
+    end
+
+
+    # resolve it to a dns name (reverse lookup)
+    if targetname == iphost
+      put_log "Still no resolve .. we try reverse dns lookup"
+      targetname = find_reverse_dname(iphost)
+    end
+
+    return targetname
+  end
+
+  def find_cooldns(iphost, ipport)
+    put_log "find_cooldns drin"
+    current = @gameservers["#{iphost}:#{ipport}"] # only use this for reading...
+
+    my_cooldns = iphost
+
+    # we still haven't found a cool dns
+    if (my_cooldns == iphost) && (not current[:hostname_dns].to_s.empty?)
+      put_log "Try if #{current[:hostname_dns]} resolves to #{iphost}"
+      begin
+        ip_of_hostnamedns = Resolv.getaddress(current[:hostname_dns])
+        if ip_of_hostnamedns && (ip_of_hostnamedns == iphost)
+          # ok, we take it.
+          put_log "Ok, we take #{current[:hostname_dns]} for #{iphost} here.."
+          my_cooldns = current[:hostname_dns]
+        else
+          put_log "Found #{current[:hostname_dns]} but #{ip_of_hostnamedns} is not #{iphost}"
+        end
+      rescue Exception => e
+        my_cooldns = iphost
+      end
+    end
+
+    # we still haven't found a cool dns
+    if (my_cooldns == iphost) && (not current[:reverse_dns].empty?)
+
+      rdns = current[:reverse_dns]
+
+      # if the resulting dns name...
+      # .. is too long, use ip-address instead.
+      # .. has too many dots, use ip-address instead.
+      # .. has too many numbers, use ip-address instead.
+      if rdns.length > 21 || rdns.split(".").size > 3 || rdns.scan(/\d/).size > 3
+        put_log "cutting down host_name: #{rdns}, because:"
+        put_log "length: #{rdns.length}"
+        put_log "chunks count: #{rdns.split(".").size}"
+        put_log "num count: #{rdns.scan(/\d/).size}"
+      else
+        my_cooldns = rdns
+      end # of Resolv.getname
+    end
+
+    put_log "COOOOOOOOOOOOLDNS: #{my_cooldns}"
+
+    my_cooldns
+  end
+
+
+  def find_reverse_dname(iphost)
+    put_log "find_reverse_dname drin"
+    Resolv.getname(iphost)
+  rescue
+    iphost
+  end
+
+  def qw_find_dname_by_udp(iphost, ipport)
+    targetname = iphost # set a default
+
+    # get hostname from a qw status packet! perhaps there's a DNS name inside, which we can use!
+    status = qwstatus(iphost, ipport)
+    p status
+
+    if status["hostname"] =~ /([\w\.-]{3,}\.\w{2,4})/
+      hostnamedns = $1.downcase
+
+      begin
+        ip_of_hostnamedns = Resolv.getaddress(hostnamedns)
+        if ip_of_hostnamedns && (ip_of_hostnamedns == iphost)
+          # ok, we take it.
+          put_log "Ok, we take #{hostnamedns} for #{iphost} here.."
+          targetname = hostnamedns
+        else
+          put_log "Found #{hostnamedns} but #{ip_of_hostnamedns} is not #{iphost}"
+        end
+      rescue Exception => e
+        targetname = iphost
+      end
+
+    end
+
+    targetname
+  end
+
+  def qw_find_dname_by_serverinfos(serverinfos)
+    hostnamedns = ""
+    begin
+      hostname = serverinfos.fetch("hostname")
+
+      if hostname =~ /([\w\.-]{3,}\.\w{2,4})/
+        hostnamedns = $1.downcase
+      end
+      return hostnamedns
+
+    rescue
+      return ""
+    end
+  end
+
+end # of Class GameServers!
+
+
+
+
+
+
 
 def string2bytearray(text)
   return_array = Array.new
@@ -68,60 +627,24 @@ def string2bytearray(text)
   return_array
 end
 
-def qwstatus(iphost, ipport)
-  udp_payload = [0xFF, 0xFF, 0xFF, 0xFF]
-  udp_payload.concat(string2bytearray("status 23"))
-  udp_payload.concat([0x0a]) # linefeed at the end
-
-  udp_payload = udp_payload.pack("C*")
-  #p udp_payload
-
-  u2 = UDPSocket.new
-  u2.send(udp_payload, 0, iphost, ipport)
-  the_return = u2.recv(1500)
-  u2.close
-
-  put_log "muh #{the_return}"
-  if the_return =~ /\W\W\W\Wn\\(.+)$/
-    line = $1
-    put_log "line #{line}"
-    matches = line.scan(/(.+?)\\(.+?)(\\|$)/)
-
-    the_hash = Hash.new
-    matches.each {
-      |k, v, _|
-      the_hash[k] = "#{v}"
-    }
-    return the_hash
-  else
-    return false
-  end
-
+def put_log(msg)
+  puts "#{Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")}: #{msg}"
 end
 
 
-module HandleQwStatus
-  attr_accessor :received
 
-  def received
-    puts "lol: #{@data}"
-    @data
-  end
-  def receive_data(data)
 
-    puts "lal: #{data}"
-    @data = data
 
-    self.received
-  end
-end
 
 module CentralProtocolHandler
 	
 	@@connected_clients = Array.new
 	@@broadcasts = Hash.new
+  put_log "Server started"
+
 
-	# default method that is being run on connection!
+
+  # default method that is being run on connection!
 	def post_init # connection of someone starts here...
 		@username = nil
 	end
@@ -175,10 +698,6 @@ module CentralProtocolHandler
 
 
 	### actions
-	def put_log(msg)
-		puts "#{Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")}: #{msg}"
-	end
-
 	# searches through our hash of saved connections and writes them a messages.
 	def	write_user(input, username = nil)
 		if username.nil? || username.empty?
@@ -301,10 +820,10 @@ module CentralProtocolHandler
 						error = 1
 					end
 
-				else # of check syntax
+				else # of payload has format
 					write_user("SYS Command format is REQ_BC <network>,<frequency>,<source/channel>,'<nickname>','<message>'")
 					error = 1
-				end
+				end # of payload has format
 
 				if error == 0
 
@@ -329,46 +848,7 @@ module CentralProtocolHandler
               c = GeoIP.new('GeoIP.dat').country(iphost)[3].to_s.downcase
               rest.prepend " #{c}" unless c.nil? || c.empty?
 
-
-              # resolve it to a dns name (reverse lookup)
-              if targetname == iphost # if it is still default
-                put_log "Ip not resolved .. we try hostname dns finder"
-                # get hostname from a qw status packet! perhaps there's a DNS name inside, which we can use! fixme
-                status = qwstatus(iphost, ipport)
-                p status
-                if status["hostname"] =~ /([\w\.]{3,}\.\w{2,4})/
-                  hostnamedns = $1.downcase
-                  ip_of_hostnamedns = Resolv.getaddress(hostnamedns)
-                  if ip_of_hostnamedns && (ip_of_hostnamedns == iphost)
-                    # ok, we take it.
-                    put_log "Ok, we take #{hostnamedns} for #{iphost} here.."
-                    targetname = hostnamedns
-                  else
-                    put_log "Found #{hostnamedns} but #{ip_of_hostnamedns} is not #{iphost}"
-                  end
-                end
-              end
-
-              # resolve it to a dns name (reverse lookup)
-              if targetname == iphost # if it is still default
-                put_log "Still no resolve .. we try reverse dns lookup"
-                resulting_name = Resolv.getname(iphost)
-                if resulting_name
-                  # if the resulting dns name...
-                  # .. is too long, use ip-address instead.
-                  # .. has too many dots, use ip-address instead.
-                  # .. has too many numbers, use ip-address instead.
-                  if resulting_name.length > 21 || resulting_name.split(".").size > 3 || resulting_name.scan(/\d/).size > 3
-                    put_log "cutting down host_name: #{resulting_name}, because:"
-                    put_log "#{resulting_name.length}"
-                    put_log "#{resulting_name.split(".").size}"
-                    put_log "#{resulting_name.scan(/\d/).size}"
-                  else
-                    targetname = resulting_name
-                  end # of Resolv.getname
-                end
-
-              end
+              targetname = $gs.get_cool_dns(iphost, ipport)
 
             end # if ip is x.x.x.x
 
@@ -381,9 +861,26 @@ module CentralProtocolHandler
 
 
 				end
-				#end of REQ_BC here..
+  		#end of REQ_BC here..
 
-			elsif cmd == "BC_RE"
+      elsif cmd == "REQ_DNS"
+        # help with format .. but send the raw payload
+        if payload =~ /^(\d+\.\d+\.\d+\.\d+):(\d{1,5})/
+          iphost = $1
+          ipport = $2
+
+          targetname = $gs.get_cool_dns(iphost, ipport)
+
+          write_user("DNS_RE #{iphost}:#{ipport} #{targetname}") # write back to asking user.
+
+        else # of payload has format
+          write_user("SYS Command format is REQ_DNS <serverip>:<serverport>")
+          error = 1
+        end # of if payload has format
+      #end of REQ_DNS here..
+
+
+        elsif cmd == "BC_RE"
 
 				if payload =~ /^(.+) (.+)=(\d+),(.+)=(\d+)$/
 
@@ -499,34 +996,30 @@ module CentralProtocolHandler
 	end
 end
 
-
-
 def main
 	# #run: Note that this will block current thread.
-	EventMachine.run do
-    EventMachine.start_server("0.0.0.0", 7337, CentralProtocolHandler)
-  end
-
-end
-
-main
-
-
-
-
-
-
-
-
-
-
-
 
+    $gs = GameServers.new
 
+    EventMachine.run do
 
+      # initial scan
+      EM.defer do
+        $gs.scanserverlist($qw_list, "qw") # initial scan
+      end
 
+      # periodic scan, 20 hours
+      EventMachine.add_periodic_timer( 60 * 60 * 20 ) {
+        EM.defer do
+          $gs.scanserverlist($qw_list, "qw") # initial scan
+        end
+      }
 
+      EventMachine.start_server("0.0.0.0", 7337, CentralProtocolHandler)
+    end
 
+end
 
+main