parent
104cc5166a
commit
1db64fe052
@ -1 +1,2 @@ |
||||
*~ |
||||
*.pyc |
||||
|
||||
@ -0,0 +1,67 @@ |
||||
#!/usr/bin/python |
||||
|
||||
import xmpp, os, hashlib, time |
||||
from datetime import datetime |
||||
|
||||
ID=0 |
||||
|
||||
JINGLE_NS = 'urn:xmpp:jingle:1' |
||||
JINGLE_FT_NS = 'urn:xmpp:jingle:apps:file-transfer:3' |
||||
JINGLE_TRANSPORT_S5B_NS = 'urn:xmpp:jingle:transports:s5b:1' |
||||
HASHES_NS = 'urn:xmpp:hashes:1' |
||||
|
||||
|
||||
def create_init_message(mfrom,to,path,desc,host,port): |
||||
global ID |
||||
ID+=1 |
||||
iq=xmpp.Iq(xmlns=None, |
||||
attrs={'to':to,'id':"jin_ft_iq_%d" % ID,'type':'set'}) |
||||
jingle=__create_jingle_node(mfrom,'session-initiate',"jin_ft_%d" % ID) |
||||
iq.getChildren().append(jingle) |
||||
|
||||
cont=__create_content_node('initiator',time.time(),path,desc) |
||||
jingle.getChildren().append(cont) |
||||
tr = __create_transport_tcp_direct(mfrom,host,port,126<<8+127,ID) |
||||
cont.getChildren().append(tr) |
||||
return iq |
||||
|
||||
def __create_jingle_node(initiator,action,sid): |
||||
return xmpp.Protocol(name="jingle",xmlns=JINGLE_NS, |
||||
attrs={'initiator':initiator,'action':action,'sid':sid}) |
||||
|
||||
|
||||
def __create_content_node(creator,date,path,txt): |
||||
mfile=open(path,"r") |
||||
datefmt = datetime.fromtimestamp(date).strftime("%Y-%m-%dT%H:%M:%SZ") |
||||
name=os.path.basename(path) |
||||
size=os.path.getsize(path) |
||||
mhash=hashlib.sha1() |
||||
mhash.update(mfile.read()) |
||||
mfile.close() |
||||
|
||||
cont= xmpp.Protocol(name="content",attrs={'creator':creator,'name':name}) |
||||
desc = cont.addChild(name="description",namespace=JINGLE_FT_NS) |
||||
offer = desc.addChild(name="offer") |
||||
mfile = offer.addChild(name="file") |
||||
|
||||
mfile.addChild(name="date",payload=[datefmt]) |
||||
mfile.addChild(name="desc",payload=[txt]) |
||||
mfile.addChild(name="name",payload=[name]) |
||||
mfile.addChild(name="size",payload=[size]) |
||||
mfile.addChild(name="hash",payload=[mhash.hexdigest()], |
||||
attrs={'algo':'sha-1'},namespace=HASHES_NS) |
||||
|
||||
return cont |
||||
|
||||
def __create_transport_tcp_direct(mfrom,host,port,priority,id): |
||||
tr = xmpp.Protocol(name="transport", |
||||
attrs={'mode':'tcp','sid':"jin_ft_tr_%d" % id}) |
||||
tr.addChild(name="candidate",attrs={ |
||||
'cid':"jin_ft_cd_%d" % id, |
||||
'host':host, |
||||
'jid':mfrom, |
||||
'port':port, |
||||
'priority':priority, |
||||
'type':'direct'}) |
||||
return tr |
||||
|
||||
@ -0,0 +1,52 @@ |
||||
import socket, random |
||||
|
||||
def s5b_prepare(): |
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
||||
|
||||
port = None |
||||
while True: |
||||
port = random.randint(10000,2**16-1) |
||||
try: |
||||
s.bind(('', port)) |
||||
s.listen(1) |
||||
break |
||||
except socket.error: |
||||
pass |
||||
|
||||
return (s,port) |
||||
|
||||
def s5b_write_file(s,fd,size): |
||||
s.settimeout(20) |
||||
conn, addr = s.accept() |
||||
data = conn.recv(3) |
||||
|
||||
assert data[0]=='\x05' #SOCKS version not 5 |
||||
assert data[1]=='\x01' #not a connect command |
||||
assert data[2]=='\x00' #does not support other connection method |
||||
|
||||
#send VER=5 METHOD=NO_AUTH |
||||
conn.sendall('\x05\x00') |
||||
|
||||
data = conn.recv(47) |
||||
|
||||
assert data[0]=='\x05' # SOCKS version not 5 |
||||
assert data[1]=='\x01' # not a connect command |
||||
# data[2] is reserved |
||||
assert data[3]=='\x03' # addr type is name |
||||
assert data[4]=='(' |
||||
name = data[5:45] |
||||
assert data[45]=='\x00' |
||||
assert data[46]=='\x00' |
||||
|
||||
#ACK |
||||
conn.sendall('\x05\x00\x00'+'\x03('+name+'\x00\x00') |
||||
#send file |
||||
data = fd.read(min(size,1024)) |
||||
size -= len(data) |
||||
while data!='': |
||||
conn.sendall(data) |
||||
data = fd.read(min(size,1024)) |
||||
size -= len(data) |
||||
|
||||
conn.close() |
||||
fd.close() |
||||
@ -0,0 +1,164 @@ |
||||
|
||||
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 |
||||
|
||||
|
||||
@ -0,0 +1,39 @@ |
||||
import select |
||||
import socket |
||||
import threading |
||||
import random |
||||
from Queue import Queue, Empty |
||||
|
||||
MAGIC_PACKET = "" |
||||
for i in xrange(50): |
||||
MAGIC_PACKET += chr(random.randrange(ord('a'),ord('z'))) |
||||
|
||||
def get_local_ip(): |
||||
def udp_listening_server(): |
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
||||
s.bind(('<broadcast>', 8888)) |
||||
s.setblocking(0) |
||||
while True: |
||||
result = select.select([s],[],[]) |
||||
msg, address = result[0][0].recvfrom(1024) |
||||
msg = unicode(msg) |
||||
if msg == MAGIC_PACKET: |
||||
break |
||||
queue.put(address) |
||||
|
||||
queue = Queue() |
||||
thread = threading.Thread(target=udp_listening_server) |
||||
thread.queue = queue |
||||
thread.start() |
||||
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
||||
s2.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) |
||||
waiting = True |
||||
while waiting: |
||||
s2.sendto(bytes(MAGIC_PACKET), ('<broadcast>', 8888)) |
||||
try: |
||||
address = queue.get(False) |
||||
except Empty: |
||||
pass |
||||
else: |
||||
waiting = False |
||||
return address[0] |
||||
Loading…
Reference in new issue