Jabber/XMPP conference bot & framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
brathuhn/stream_ft.py

164 lines
3.8 KiB

import xmpp, os, hashlib, time, brathuhn
import socket, subprocess, random, s5b, util
import config
from threading import Thread
from datetime import datetime
GET_IP_CMD = ["dig", "myip.opendns.com", "@resolver1.opendns.com", "+short"]
PROXY = config.S5B_PROXY
ID=random.randint(0,1000000)
BSTREAM_NS = "http://jabber.org/protocol/bytestreams"
SI_NS = 'http://jabber.org/protocol/si'
FILE_NS = 'http://jabber.org/protocol/si/profile/file-transfer'
FEATURE_NS = 'http://jabber.org/protocol/feature-neg'
X_DATA_NS = 'jabber:x:data'
JABBER_NS = 'jabber:client'
BYTESTREAM = 'http://jabber.org/protocol/bytestreams'
IBB = 'http://jabber.org/protocol/ibb'
transfer_ids = dict()
queries = dict()
LOCAL_IP = util.get_local_ip()
def create_init_message(mfrom,to,name,size,fd):
global ID
global transfer_ids
ID+=1
transfer_ids[unicode("si_%d"%ID)]=[fd,ID,size]
iq=xmpp.Iq(xmlns=JABBER_NS,
attrs={'from':unicode(mfrom),'to':to,'id':"si_%d" % ID,'type':'set'})
si=iq.addChild(name="si",namespace=SI_NS, attrs={'id':"si_%d" % ID, 'profile':FILE_NS})
si.addChild(name="file", namespace=FILE_NS, attrs={'name':name,'size':size})
fr=si.addChild(name="feature", namespace=FEATURE_NS)
x=fr.addChild(name="x", namespace=X_DATA_NS, attrs={'type':'form'})
fd=x.addChild(name="field",attrs={'type':'list-single','var':'stream-method'})
opt=fd.addChild(name="option")
val=opt.addChild(name="value")
val.addData(BYTESTREAM)
opt=fd.addChild(name="option")
val=opt.addChild(name="value")
val.addData(IBB)
return iq
def create_bytestream_query_message(mfrom,to,port,cid):
global queries
sid = "si_%d" % cid
queries[sid] = cid
iq=xmpp.Iq(xmlns=JABBER_NS,
attrs={'from':unicode(mfrom),'to':to,'id':sid,'type':'set'})
q = iq.addChild(name="query",namespace=BSTREAM_NS, attrs={'sid':sid})
hosts = []
p=subprocess.Popen(GET_IP_CMD,stdout=subprocess.PIPE)
p.wait()
hosts.append(p.stdout.read())
hosts.append(LOCAL_IP)
for host in hosts:
q.addChild(name="streamhost",attrs={'jid':unicode(mfrom),'port':str(port),'host':host})
#print "<!--out-->\n",q
return iq
def start_ibb(cid,mfrom,fd):
print "IBB"
stream = xmpp.filetransfer.IBB()
stream.PlugIn(brathuhn.cl)
stream.OpenStream("si_%d" % cid, mfrom, fd, blocksize=4096)
def ft_query(conn,msg):
global queries
global transfer_ids
sid = msg.attrs['id']
cid = queries[sid]
assert sid in transfer_ids
fd = transfer_ids[ sid ][0]
if msg.attrs['type']=='error':
start_ibb(cid, unicode(msg.getFrom()), fd)
del transfer_ids[ sid ]
del queries[ sid ]
def ft_init(conn,msg):
global ID
sid = msg.attrs['id']
if msg.attrs['type']=='result':
fd = transfer_ids[ sid ][0]
size = transfer_ids[ sid ][2]
current_id = transfer_ids[ sid ][1]
else:
del transfer_ids[ sid ]
return
si=msg.getChildren()[0]
# check if cancel message
if si.name!='si':
return
fr=si.getChildren()[0]
# some clients send a profile name
# we will ignore it i.e take the next child
if fr.name=='file':
fr=si.getChildren()[1]
if fr.name!='feature':
return
x=fr.getChildren()[0]
if x.name!='x' and x.attrs['type']!='submit':
return
fi=x.getChildren()[0]
if fi.name!='field':
return
val=fi.getChildren()[0]
if val.name!='value':
return
if val.data[0]==BYTESTREAM:
print "BYTESTREAM"
s,port=s5b.s5b_prepare()
q = create_bytestream_query_message(brathuhn.room_nick,msg.getFrom(),port,current_id)
brathuhn.cl.send(q)
def __run():
s5b.s5b_write_file(s,fd,size)
Thread(target=__run()).start()
ID += 1
elif val.data[0]==IBB:
start_ibb(current_id, unicode(msg.getFrom()), fd)
def ft_listener(conn,msg):
global transfer_ids
global queries
assert msg.name=='iq'
sid = msg.attrs['id']
if sid in transfer_ids and not sid in queries:
print "init"
ft_init(conn,msg)
return
if sid in queries:
ft_query(conn,msg)
return