#
# heartbeat.py: Iceball heartbeat server
# This file is part of Iceball.
#
# Iceball is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Iceball is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Iceball. If not, see .
#
import errno, heapq, json, operator, random, socket, struct, sys, time
CONN_PORT = int(sys.argv[1])
def ib_version_str(n):
z = n & ((1<<10)-1); n >>= 10
a = n & ((1<<5)-1); n >>= 5
y = n & ((1<<7)-1); n >>= 7
x = n & ((1<<5)-1); n >>= 5
w = n
s = "%i.%i" % (w, x)
if y > 0:
s += ".%i" % y
if a > 0:
s += chr(ord('a')+a-1)
if z > 0:
s += "-%i" % z
return s
def calc_ib_version(w,x,y,a,z):
return (((((((w<<5) + x
)<<7) + y
)<<5) + a
)<<10) + z
HB_LIFETIME = 120
HB_VERSION = 2
IB_VERSION_CMP = (0,2,1,0,35)
IB_VERSION = calc_ib_version(*IB_VERSION_CMP)
# ignore "Z" version
IB_VERSION_MASK = ~((1<<10)-1)
# if you wish to ignore "A" version as well, use this instead:
# IB_VERSION_MASK = ~((1<<(10+5))-1)
PRIORITY_DEFAULT = 0
PRIORITY_OFFICIAL = 1
PRIORITY_SERVERS = {}
OFFICIAL_SERVERS = set()
try:
with open("servers.json", "r") as fp:
p = json.load(fp)
# Server priorities
for k, v in p["server_priorities"].iteritems():
if not isinstance(k, (str, unicode)) or not isinstance(v, int):
print 'Invalid server priority entry in servers.json - skipping: "%s", "%s"' % (k, v)
break
else:
PRIORITY_SERVERS = p["server_priorities"]
# Official servers
for v in p["official_servers"]:
if not isinstance(v, (str, unicode)):
print 'Invalid official server entry in servers.json - ignoring: "%s"' % v
else:
OFFICIAL_SERVERS.add(v)
# Default priority values
PRIORITY_DEFAULT = p.get("default_priority", PRIORITY_DEFAULT)
PRIORITY_OFFICIAL = p.get("official_priority", PRIORITY_OFFICIAL)
# Cleanup
del p
except IOError:
print "Could not read servers.json - skipping"
except AttributeError:
print "Error in servers.json - skipping"
def stripnul(s):
idx = s.find("\x00")
return (s if idx == -1 else s[:idx])
def replace_char_all(s, f, t):
v = ord(f)
s = s.replace(f, t)
s = s.replace(chr(0xC0 | ((v>>6)&3)) + chr(0x80 | (v&63)), t)
s = s.replace(chr(0xE0) + chr(0x80 | ((v>>6)&3)) + chr(0x80 | (v&63)), t)
s = s.replace(chr(0xF0) + chr(0x80) + chr(0x80 | ((v>>6)&3)) + chr(0x80 | (v&63)), t)
s = s.replace(chr(0xF8) + chr(0x80) + chr(0x80) + chr(0x80 | ((v>>6)&3)) + chr(0x80 | (v&63)), t)
s = s.replace(chr(0xFC) + chr(0x80) + chr(0x80) + chr(0x80) + chr(0x80 | ((v>>6)&3)) + chr(0x80 | (v&63)), t)
# TODO: handle the 6-bit and 8-bit variants and whatnot
return s
def sanestr(s):
s = str(s)
s = replace_char_all(s, "&", "&")
s = replace_char_all(s, "<", "<")
s = replace_char_all(s, ">", ">")
return s
class HTTPClient:
def __init__(self, ct, reactor, server, sockfd):
self.reactor = reactor
self.server = server
self.sockfd = sockfd
self.buf = ""
self.wbuf = None
self.sockfd.setblocking(False)
self.reactor.push(ct, self.update)
def is_dead(self, ct):
return self.sockfd == None
def update(self, et, ct):
self.get_msgs(ct)
self.push_buf(ct)
if self.sockfd:
self.reactor.push(ct + 0.1, self.update)
def get_file_index(self):
l = self.server.get_ib_fields()
s = "\n
\n"
s += "Iceball Server List\n"
s += "\n"
s += "\n"
s += "\n\n"
s += "