from twisted.web import resource, server, static
from twisted.names import client
from twisted.internet import reactor
-import simplejson, md5, sys, os, ircclient, time, config
+import traceback
+import simplejson, md5, sys, os, ircclient, time, config, weakref
Sessions = {}
def get_session_id():
- return md5.md5(os.urandom(16)).hexdigest()
-
+ return md5.md5(os.urandom(16)).hexdigest()[:10]
+
+class BufferOverflowException(Exception):
+ pass
+
+class IDGenerationException(Exception):
+ pass
+
def jsondump(fn):
def decorator(*args, **kwargs):
x = fn(*args, **kwargs)
return x
return decorator
+def cleanupSession(id):
+ try:
+ del Sessions[id]
+ except KeyError:
+ pass
+
class IRCSession:
def __init__(self, id):
self.id = id
self.buffer = []
self.throttle = 0
self.schedule = None
-
+ self.closed = False
+ self.cleanupschedule = None
+
def subscribe(self, channel):
+ if len(self.subscriptions) >= config.MAXSUBSCRIPTIONS:
+ self.subscriptions.pop(0)
+
self.subscriptions.append(channel)
self.flush()
newsubs.append(x)
self.subscriptions = newsubs
-
+ if self.closed and not self.subscriptions:
+ cleanupSession(self.id)
+
def event(self, data):
+ bufferlen = sum(map(len, self.buffer))
+ if bufferlen + len(data) > config.MAXBUFLEN:
+ self.buffer = []
+ self.client.error("Buffer overflow")
+ return
+
self.buffer.append(data)
self.flush()
def push(self, data):
- self.client.write(data)
-
+ if not self.closed:
+ self.client.write(data)
+
+ def disconnect(self):
+ # keep the session hanging around for a few seconds so the
+ # client has a chance to see what the issue was
+ self.closed = True
+
+ reactor.callLater(5, cleanupSession, self.id)
+
class Channel:
def __init__(self, request):
self.request = request
return [False, "Nickname not supplied"]
nick = nick[0]
-
- id = get_session_id()
-
+
+ for i in xrange(10):
+ id = get_session_id()
+ if not Sessions.get(id):
+ break
+ else:
+ raise IDGenerationException()
+
session = IRCSession(id)
- client = ircclient.createIRC(session, nick=nick, ident=ident, ip=ip, realname=nick)
+ client = ircclient.createIRC(session, nick=nick, ident=ident, ip=ip, realname=config.REALNAME)
session.client = client
Sessions[id] = session
decoded = command.decode("utf-8")
except UnicodeDecodeError:
decoded = command.decode("iso-8859-1", "ignore")
- session.push(decoded)
+
+ try:
+ session.push(decoded)
+ except AttributeError: # occurs when we haven't noticed an error
+ session.disconnect()
+ return [False, "Connection closed by server."]
+ except Exception, e: # catch all
+ session.disconnect()
+ traceback.print_exc(file=sys.stderr)
+ return [False, "Unknown error."]
+
return [True]
return [False, "404"]