mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-27 13:09:23 +01:00
unreal: Niceties like PING/PONG handling and enumerating our uplink's server
This commit is contained in:
parent
58b00d1c23
commit
18dc1591aa
@ -12,6 +12,7 @@ import proto_common
|
||||
from classes import *
|
||||
|
||||
casemapping = 'ascii'
|
||||
proto_ver = 2351
|
||||
|
||||
hook_map = {}
|
||||
|
||||
@ -22,11 +23,17 @@ def joinClient(irc, client, channel):
|
||||
pass
|
||||
|
||||
def pingServer(irc, source=None, target=None):
|
||||
pass
|
||||
source = source or irc.sid
|
||||
target = target or irc.uplink
|
||||
if not (target is None or source is None):
|
||||
_send(irc, source, 'PING %s %s' % (irc.servers[source].name, irc.servers[target].name))
|
||||
|
||||
def _send(irc, sid, msg):
|
||||
irc.send(':%s %s' % (sid, msg))
|
||||
|
||||
def connect(irc):
|
||||
ts = irc.start_ts
|
||||
proto_ver = 2351
|
||||
irc.caps = []
|
||||
|
||||
f = irc.send
|
||||
host = irc.serverdata["hostname"]
|
||||
@ -39,22 +46,74 @@ def connect(irc):
|
||||
# SID - Use UIDs and SIDs (unreal 3.4)
|
||||
# VL - Sends version string in below SERVER message
|
||||
# UMODE2 - used for users setting modes on themselves (one less argument needed)
|
||||
# TS - Sends TS in burst to mitigate time-based desyncs.
|
||||
f('PROTOCTL SJ3 NOQUIT NICKv2 VL UMODE TS EAUTH=%s' % irc.serverdata["hostname"])
|
||||
f('PROTOCTL SID=%s TS=%s' % (irc.sid, ts))
|
||||
f('SERVER %s 1 U%s-h6e-%s' % (host, proto_ver, irc.sid))
|
||||
f('EOS')
|
||||
# NETINFO maxglobal currenttime protocolversion cloakhash 0 0 0 :networkname
|
||||
# EAUTH - Early auth? (Unreal 3.4 linking protocol)
|
||||
f('PROTOCTL SJ3 NOQUIT NICKv2 VL UMODE2 PROTOCTL EAUTH=%s SID=%s' % (irc.serverdata["hostname"], irc.sid))
|
||||
sdesc = irc.serverdata.get('serverdesc') or irc.botdata['serverdesc']
|
||||
f('SERVER %s 1 U%s-h6e-%s :%s' % (host, proto_ver, irc.sid, sdesc))
|
||||
# Now, we wait until remote sends its NETINFO command (handle_netinfo),
|
||||
# so we can find and use a matching netname, preventing netname mismatch
|
||||
# errors.
|
||||
|
||||
def handle_netinfo(irc, numeric, command, args):
|
||||
# <- NETINFO maxglobal currenttime protocolversion cloakhash 0 0 0 :networkname
|
||||
# "maxglobal" is the amount of maximum global users we've seen so far.
|
||||
# We'll just set it to 1 (the PyLink client), since this is completely
|
||||
# arbitrary.
|
||||
f('NETINFO 1 %s %s * 0 0 0 :networkname' % (ts, proto_ver))
|
||||
irc.send('NETINFO 1 %s %s * 0 0 0 :%s' % (irc.start_ts, proto_ver, args[-1]))
|
||||
_send(irc, irc.sid, 'EOS')
|
||||
|
||||
def handle_uid(irc, numeric, command, args):
|
||||
# <- :001 UID GL 0 1441306929 gl localhost 0018S7901 0 +iowx * midnight-1C620195 fwAAAQ== :realname
|
||||
# <- :001 UID GL| 1 1441312224 gl localhost 001J7FZ02 0 +iwx midnight-1C620195 midnight-1C620195 fwAAAQ== :realname
|
||||
pass
|
||||
|
||||
def handle_pass(irc, numeric, command, args):
|
||||
# <- PASS :abcdefg
|
||||
if args[0] != irc.serverdata['recvpass']:
|
||||
raise ProtocolError("Error: RECVPASS from uplink does not match configuration!")
|
||||
|
||||
def handle_ping(irc, numeric, command, args):
|
||||
if numeric == irc.uplink:
|
||||
irc.send('PONG %s :%s' % (irc.serverdata['hostname'], args[-1]))
|
||||
|
||||
def handle_pong(irc, source, command, args):
|
||||
log.debug('(%s) Ping received from %s for %s.', irc.name, source, args[-1])
|
||||
if source in (irc.uplink, irc.servers[irc.uplink].name) and args[-1] == irc.serverdata['hostname']:
|
||||
log.debug('(%s) Set irc.lastping.', irc.name)
|
||||
irc.lastping = time.time()
|
||||
|
||||
def handle_server(irc, numeric, command, args):
|
||||
# <- SERVER unreal.midnight.vpn 1 :UnrealIRCd test server
|
||||
sname = args[0]
|
||||
# TODO: handle server introductions from other servers
|
||||
if numeric == irc.uplink:
|
||||
irc.servers[numeric] = IrcServer(None, sname)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
_unrealCmodes = {'l': 'limit', 'c': 'blockcolor', 'G': 'censor',
|
||||
'D': 'delayjoin', 'n': 'noextmsg', 's': 'secret',
|
||||
'T': 'nonotice', 'z': 'sslonly', 'b': 'ban', 'V': 'noinvite',
|
||||
'Z': 'issecure', 'r': 'registered', 'N': 'nonick',
|
||||
'e': 'banexception', 'R': 'regonly', 'M': 'regmoderated',
|
||||
'p': 'private', 'Q': 'nokick', 'P': 'permanent', 'k': 'key',
|
||||
'C': 'noctcp', 'O': 'operonly', 'S': 'stripcolor',
|
||||
'm': 'moderated', 'K': 'noknock', 'o': 'op', 'v': 'voice',
|
||||
'I': 'invex', 't': 'topiclock'}
|
||||
def handle_protoctl(irc, numeric, command, args):
|
||||
# <- PROTOCTL NOQUIT NICKv2 SJOIN SJOIN2 UMODE2 VL SJ3 TKLEXT TKLEXT2 NICKIP ESVID
|
||||
# <- PROTOCTL CHANMODES=beI,k,l,psmntirzMQNRTOVKDdGPZSCc NICKCHARS= SID=001 MLOCK TS=1441314501 EXTSWHOIS
|
||||
irc.caps += args
|
||||
for cap in args:
|
||||
if cap.startswith('SID'):
|
||||
irc.uplink = cap.split('=', 1)[1]
|
||||
elif cap.startswith('CHANMODES'):
|
||||
cmodes = cap.split('=', 1)[1]
|
||||
irc.cmodes['*A'], irc.cmodes['*B'], irc.cmodes['*C'], irc.cmodes['*D'] = cmodes.split(',')
|
||||
for m in cmodes:
|
||||
if m in _unrealCmodes:
|
||||
irc.cmodes[_unrealCmodes[m]] = m
|
||||
|
||||
def handle_events(irc, data):
|
||||
# Unreal's protocol has three styles of commands, @servernumeric, :user, and plain commands.
|
||||
# e.g. NICK introduction looks like:
|
||||
@ -67,7 +126,7 @@ def handle_events(irc, data):
|
||||
# end of the line.
|
||||
args = proto_common.parseArgs(data.split(" "))
|
||||
# Message starts with a SID/UID prefix.
|
||||
if args[0] in ':@':
|
||||
if args[0][0] in ':@':
|
||||
numeric = args[0].lstrip(':@')
|
||||
command = args[1]
|
||||
args = args[2:]
|
||||
|
Loading…
Reference in New Issue
Block a user