Move things into factories and implement reconnecting

pull/1/head
Mark Veidemanis 7 years ago
parent cd8c61cdc6
commit 88426be62a

@ -21,6 +21,10 @@
"protocol": null, "protocol": null,
"bind": null, "bind": null,
"timeout": 30, "timeout": 30,
"maxdelay": 5,
"initialdelay": 1,
"factor": 2,
"jitter": 5,
"nickname": null, "nickname": null,
"username": null, "username": null,
"realname": null, "realname": null,
@ -33,8 +37,7 @@
"password": null, "password": null,
"authentity": "NickServ", "authentity": "NickServ",
"key": "key.pem", "key": "key.pem",
"certificate": "cert.pem", "certificate": "cert.pem"
"enabled": true
}, },
"Master": [null, null] "Master": [null, null]
} }

@ -2,8 +2,7 @@
from twisted.internet import reactor from twisted.internet import reactor
from twisted.internet.defer import Deferred from twisted.internet.defer import Deferred
from twisted.internet.ssl import DefaultOpenSSLContextFactory from twisted.internet.ssl import DefaultOpenSSLContextFactory
from twisted.internet.protocol import Protocol, Factory from twisted.internet.protocol import Protocol, Factory, ClientFactory, ReconnectingClientFactory
from twisted.internet.endpoints import SSL4ClientEndpoint, TCP4ClientEndpoint, connectProtocol
from twisted.words.protocols.irc import IRCClient from twisted.words.protocols.irc import IRCClient
#from twisted.python import log #from twisted.python import log
@ -19,6 +18,8 @@ numbers = "0123456789"
listener = None listener = None
connections = {} connections = {}
IRCPool = {} IRCPool = {}
ReactorPool = {}
FactoryPool = {}
MonitorPool = [] MonitorPool = []
@ -246,19 +247,39 @@ class IRCBot(IRCClient):
nick, ident, host = self.parsen(user) nick, ident, host = self.parsen(user)
helper.setWhoSingle(self.name, nick, ident, host) helper.setWhoSingle(self.name, nick, ident, host)
def connectionLost(self, reason): class IRCBotFactory(ReconnectingClientFactory):
self.connected = False def __init__(self, name):
self.channels = [] self.instance = pool[name]
self.name = name
self.maxDelay = self.instance["maxdelay"]
self.initialDelay = self.instance["initialdelay"]
self.factor = self.instance["factor"]
self.jitter = self.instance["jitter"]
def buildProtocol(self, addr):
global IRCPool
entry = IRCBot(self.name)
IRCPool[self.name] = entry
self.client = entry
return entry
def clientConnectionLost(self, connector, reason):
self.client.connected = False
self.client.channels = []
error = reason.getErrorMessage() error = reason.getErrorMessage()
log("%s: connection lost: %s" % (self.name, error)) log("%s: connection lost: %s" % (self.name, error))
helper.sendAll("%s: connection lost: %s" % (self.name, error)) helper.sendAll("%s: connection lost: %s" % (self.name, error))
self.retry(connector)
#ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
def connectionFailed(self, reason): def clientConnectionFailed(self, connector, reason):
self.connected = False self.client.connected = False
self.channels = [] self.client.channels = []
error = reason.getErrorMessage() error = reason.getErrorMessage()
log("%s: connection failed: %s" % (self.name, error)) log("%s: connection failed: %s" % (self.name, error))
helper.sendAll("%s: connection failed: %s" % (self.name, error)) helper.sendAll("%s: connection failed: %s" % (self.name, error))
self.retry(connector)
#ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
class Base(Protocol): class Base(Protocol):
def __init__(self, addr): def __init__(self, addr):
@ -431,32 +452,37 @@ class Helper(object):
log("Started bot %s to %s:%s protocol %s nickname %s" % (name, instance["host"], instance["port"], instance["protocol"], instance["nickname"])) log("Started bot %s to %s:%s protocol %s nickname %s" % (name, instance["host"], instance["port"], instance["protocol"], instance["nickname"]))
if instance["protocol"] == "plain": if instance["protocol"] == "plain":
if instance["bind"] == None: if instance["bind"] == None:
point = TCP4ClientEndpoint(reactor, instance["host"], int(instance["port"]), timeout=int(instance["timeout"])) bot = IRCBotFactory(name)
bot = IRCBot(name) rct = reactor.connectTCP(instance["host"], instance["port"], bot, timeout=int(instance["timeout"]))
IRCPool[name] = bot
d = connectProtocol(point, bot) ReactorPool[name] = rct
FactoryPool[name] = bot
return return
else: else:
point = TCP4ClientEndpoint(reactor, instance["host"], int(instance["port"]), timeout=int(instance["timeout"]), bindAddress=instance["bind"]) bot = IRCBotFactory(name)
bot = IRCBot(name) rct = reactor.connectTCP(instance["host"], instance["port"], bot, timeout=int(instance["timeout"]), bindAddress=instance["bind"])
IRCPool[name] = bot
d = connectProtocol(point, bot) ReactorPool[name] = rct
FactoryPool[name] = bot
return return
elif instance["protocol"] == "ssl": elif instance["protocol"] == "ssl":
keyFN = certPath+instance["key"] keyFN = certPath+instance["key"]
certFN = certPath+instance["certificate"] certFN = certPath+instance["certificate"]
contextFactory = DefaultOpenSSLContextFactory(keyFN.encode("utf-8", "replace"), certFN.encode("utf-8", "replace")) contextFactory = DefaultOpenSSLContextFactory(keyFN.encode("utf-8", "replace"), certFN.encode("utf-8", "replace"))
if instance["bind"] == None: if instance["bind"] == None:
point = SSL4ClientEndpoint(reactor, instance["host"], int(instance["port"]), contextFactory, timeout=int(instance["timeout"])) bot = IRCBotFactory(name)
bot = IRCBot(name) rct = reactor.connectSSL(instance["host"], int(instance["port"]), bot, contextFactory)
IRCPool[name] = bot
d = connectProtocol(point, bot) ReactorPool[name] = rct
FactoryPool[name] = bot
return return
else: else:
point = SSL4ClientEndpoint(reactor, instance["host"], int(instance["port"]), contextFactory, timeout=int(instance["timeout"]), bindAddress=instance["bind"])
bot = IRCBot(name) bot = IRCBotFactory(name)
IRCPool[name] = bot rct = reactor.connectSSL(instance["host"], int(instance["port"]), bot, contextFactory, bindAddress=instance["bind"])
d = connectProtocol(point, bot)
ReactorPool[name] = rct
FactoryPool[name] = bot
return return
def addKeyword(self, keyword): def addKeyword(self, keyword):
@ -637,10 +663,13 @@ class Helper(object):
return return
pool[spl[1]]["enabled"] = False pool[spl[1]]["enabled"] = False
self.save("pool") self.save("pool")
if spl[1] in IRCPool.keys(): if spl[1] in ReactorPool.keys():
if IRCPool[spl[1]].connected == True: if spl[1] in FactoryPool.keys():
IRCPool[spl[1]].transport.loseConnection() FactoryPool[spl[1]].stopTrying()
del IRCPool[spl[1]] ReactorPool[spl[1]].disconnect()
del IRCPool[spl[1]]
del ReactorPool[spl[1]]
del FactoryPool[spl[1]]
success("Successfully disabled bot %s" % spl[1]) success("Successfully disabled bot %s" % spl[1])
return return
else: else:
@ -995,9 +1024,9 @@ class Helper(object):
spl[2] = None spl[2] = None
toUnset = True toUnset = True
if spl[1] in ["port", "timeout"]: if spl[1] in ["port", "timeout", "maxdelay", "initialdelay", "factor", "jitter"]:
try: try:
int(spl[2]) spl[2] = int(spl[2])
except: except:
failure("Value must be an integer, not %s" % spl[2]) failure("Value must be an integer, not %s" % spl[2])
return return
@ -1066,12 +1095,7 @@ class Helper(object):
if not spl[2] in pool[spl[1]].keys(): if not spl[2] in pool[spl[1]].keys():
failure("No such key: %s" % spl[2]) failure("No such key: %s" % spl[2])
return return
if spl[2] in ["port", "timeout"]:
try:
int(spl[3])
except:
failure("Value must be an integer, not %s" % spl[3])
return
if spl[2] == "protocol": if spl[2] == "protocol":
if not spl[3] in ["ssl", "plain"]: if not spl[3] in ["ssl", "plain"]:
failure("Protocol must be ssl or plain, not %s" % spl[3]) failure("Protocol must be ssl or plain, not %s" % spl[3])
@ -1084,6 +1108,13 @@ class Helper(object):
spl[3] = None spl[3] = None
toUnset = True toUnset = True
if spl[2] in ["port", "timeout", "maxdelay", "initialdelay", "factor", "jitter"]:
try:
spl[3] = int(spl[3])
except:
failure("Value must be an integer, not %s" % spl[3])
return
if spl[2] == "authtype": if spl[2] == "authtype":
if not toUnset: if not toUnset:
if not spl[3] in ["sp", "ns"]: if not spl[3] in ["sp", "ns"]:

Loading…
Cancel
Save