Difference between revisions of "Presence Code Python"
(updated version) |
(corrected code to decode message ID *before* parsing it) |
||
Line 1: | Line 1: | ||
Extremely incomplete example of how to log an avatar in and establish a presence. So far it only sends enough to temporarily show in-world. More to come.... | Extremely incomplete example of how to log an avatar in and establish a presence. So far it only sends enough to temporarily show in-world. More to come.... | ||
N.B.: the packet ID number of a zero encoded pack is encoded and must be decoded before you can know what packet you are actually dealing with (Thanks John Hurliman/Eddy Stryker). | |||
(based on a sample login script found at [http://www.libsecondlife.org/wiki/Login libsl login].) | (based on a sample login script found at [http://www.libsecondlife.org/wiki/Login libsl login].) | ||
Line 21: | Line 23: | ||
ack_need_list = [] | ack_need_list = [] | ||
logoutputflag = True | logoutputflag = True | ||
if logoutputflag: | if logoutputflag: | ||
temp = sys.stdout | temp = sys.stdout | ||
sys.stdout =open('alog.txt',' | sys.stdout =open('alog.txt','w') | ||
def login(first, last, passwd, mac): | def login(first, last, passwd, mac): | ||
Line 89: | Line 91: | ||
return | return | ||
else: | else: | ||
ack_need_list.append(unpack(">L",data[1:5])[0]) | ID = data[1:5] | ||
if (ord(data[0])&0x40) & 0x80: ID = zero_decode_ID(ID) | |||
ack_need_list.append(unpack(">L",ID)[0]) | |||
#ack_need_list.append(unpack(">L",data[1:5])[0]) | |||
#print "ack needed","insdie schedule ack_need_list", ack_need_list | #print "ack needed","insdie schedule ack_need_list", ack_need_list | ||
Line 176: | Line 181: | ||
else: | else: | ||
test = ByteToHex(data).split() | test = ByteToHex(data).split() | ||
#print test | |||
if | ID = data[6:12] | ||
if | #print "ID =", ByteToHex(ID) | ||
myentry = mypacketdictionary[("Fixed" , int("0x"+ByteToHex( | if (ord(data[0])&0x80): ID = zero_decode_ID(data[6:12]) | ||
#print "ID =", ByteToHex(ID) | |||
#print "ID =", unpack(">L", ID[:4]) | |||
if ID[0] == '\xFF': | |||
if ID[1] == '\xFF': | |||
if ID[2] == '\xFF': | |||
myentry = mypacketdictionary[("Fixed" , int("0x"+ByteToHex(ID[2:4]).replace(' ', ''),16))] | |||
if (ord(data[0])&0x40): | if (ord(data[0])&0x40): | ||
scheduleacknowledgemessage(data); | scheduleacknowledgemessage(data); | ||
Line 185: | Line 196: | ||
print "Message #", i,"Flags: 0x" + test[0], myentry, "sequence #", unpack(">L",data[1:5]), "ack needed" | print "Message #", i,"Flags: 0x" + test[0], myentry, "sequence #", unpack(">L",data[1:5]), "ack needed" | ||
#if myentry[1] == "Trusted": trusted_count = trusted_count +1;print "number of trusted messages =", trusted_count | |||
#if (ord(data[0])&0x40) and (myentry[1] == "Trusted"): trusted_and_ackable = trusted_and_ackable + 1; print "trusted_and_ackable =", trusted_and_ackable | |||
#if (ord(data[0])&0x40): ackable = ackable + 1; print "number of ackable messages = ", ackable | |||
else: | else: | ||
myentry = mypacketdictionary[("Low",int("0x"+ByteToHex( | myentry = mypacketdictionary[("Low",int("0x"+ByteToHex(ID[2:4]).replace(' ', ''),16))] | ||
if (ord(data[0])&0x40): | if (ord(data[0])&0x40): | ||
scheduleacknowledgemessage(data); | scheduleacknowledgemessage(data); | ||
Line 196: | Line 210: | ||
#if (ord(data[0])&0x40): ackable = ackable + 1; print "number of ackable messages = ", ackable | #if (ord(data[0])&0x40): ackable = ackable + 1; print "number of ackable messages = ", ackable | ||
else: | else: | ||
myentry = mypacketdictionary[("Medium", int("0x"+ByteToHex( | myentry = mypacketdictionary[("Medium", int("0x"+ByteToHex(ID[1:2]).replace(' ', ''),16))] | ||
if (ord(data[0])&0x40): | if (ord(data[0])&0x40): | ||
scheduleacknowledgemessage(data); | scheduleacknowledgemessage(data); | ||
Line 202: | Line 216: | ||
print "Message #", i,"Flags: 0x" + test[0], myentry, "sequence #", unpack(">L",data[1:5]) | print "Message #", i,"Flags: 0x" + test[0], myentry, "sequence #", unpack(">L",data[1:5]) | ||
#if myentry[1] == "Trusted": trusted_count = trusted_count +1;print "number of trusted messages =", trusted_count | |||
#if (ord(data[0])&0x40) and (myentry[1] == "Trusted"): trusted_and_ackable = trusted_and_ackable + 1; print "trusted_and_ackable =", trusted_and_ackable | |||
#if (ord(data[0])&0x40): ackable = ackable + 1; print "number of ackable messages = ", ackable | |||
else: | else: | ||
myentry = mypacketdictionary[("High", int("0x"+ByteToHex( | myentry = mypacketdictionary[("High", int("0x"+ByteToHex(ID[0]), 16))] | ||
if (ord(data[0])&0x40): | if (ord(data[0])&0x40): | ||
scheduleacknowledgemessage(data); | scheduleacknowledgemessage(data); | ||
Line 209: | Line 226: | ||
print "Message #", i,"Flags: 0x" + test[0], myentry, "sequence #", unpack(">L",data[1:5]) | print "Message #", i,"Flags: 0x" + test[0], myentry, "sequence #", unpack(">L",data[1:5]) | ||
#if myentry[1] == "Trusted": trusted_count = trusted_count +1;print "number of trusted messages =", trusted_count | |||
#if (ord(data[0])&0x40) and (myentry[1] == "Trusted"): trusted_and_ackable = trusted_and_ackable + 1; print "trusted_and_ackable =", trusted_and_ackable | |||
#if (ord(data[0])&0x40): ackable = ackable + 1; print "number of ackable messages = ", ackable | |||
sock.close() | sock.close() | ||
print "final number of trusted messages =", trusted_count | print "final number of trusted messages =", trusted_count | ||
Line 228: | Line 248: | ||
#cap_out = get_caps(result,"seed_capability", ["ChatSessionRequest"]) | #cap_out = get_caps(result,"seed_capability", ["ChatSessionRequest"]) | ||
Revision as of 22:34, 18 December 2007
Extremely incomplete example of how to log an avatar in and establish a presence. So far it only sends enough to temporarily show in-world. More to come....
N.B.: the packet ID number of a zero encoded pack is encoded and must be decoded before you can know what packet you are actually dealing with (Thanks John Hurliman/Eddy Stryker).
(based on a sample login script found at libsl login.)
<python>from struct import * from zerocode import * import md5 import xmlrpclib import sys
import re import httplib, urllib from urlparse import urlparse import socket, sys, time import uuid from makepacketdict import makepacketdict
mypacketdictionary = {}
outputstring =
ack_need_list = []
logoutputflag = True
if logoutputflag:
temp = sys.stdout sys.stdout =open('alog.txt','w')
def login(first, last, passwd, mac):
passwd_md5 = '$1$' + md5.new(passwd).hexdigest() uri = 'http://127.0.0.1' uri = 'https://login.agni.lindenlab.com/cgi-bin/login.cgi' s = xmlrpclib.ServerProxy(uri) login_details = { 'first': first, 'last': last, 'passwd': passwd_md5, 'start': 'last', 'major': '1', 'minor': '18', 'patch': '5', 'build': '3', 'platform': 'Win', 'mac': mac, 'options': [], 'user-agent': 'sl.py 0.1', 'id0': , 'agree_to_tos': , 'viewer_digest': '09d93740-8f37-c418-fbf2-2a78c7b0d1ea' } results = s.login_to_simulator(login_details) print results return results
def get_caps(results,cap_key, request_keys):
_, netloc, path, _, _, _ = urlparse(results[cap_key])
params = "<llsd><array><string>"+ request_keys[0]+"</string></array></llsd>" headers = {"content-type": "application/xml"} conn = httplib.HTTPSConnection(netloc)
conn.request("POST", path, params, headers) response = conn.getresponse()
data = response.read() conn.close() return data
def ExtractCap(cap_result):
trim_xml = re.compile(r"<key>([a-zA-Z_]+)</key><string>([a-zA-Z_:/0-9-.]+)</string>") new_key = trim_xml.search(cap_result).group(1) new_cap = trim_xml.search(cap_result).group(2) return new_key, new_cap
def scheduleacknowledgemessage(data):
if not (ord(data[0])&0x40): print "OOOPS! Got asked to ack a message that shouldn't be acked" return else: ID = data[1:5] if (ord(data[0])&0x40) & 0x80: ID = zero_decode_ID(ID) ack_need_list.append(unpack(">L",ID)[0]) #ack_need_list.append(unpack(">L",data[1:5])[0]) #print "ack needed","insdie schedule ack_need_list", ack_need_list
return
def packacks():
acksequence = "" for msgnum in ack_need_list: acksequence = acksequence + pack(">L", msgnum) return acksequence
- def sendacks():
# if len(ack_need_list)>0:
def sendAgentUpdate(sock, port, host, currentsequence, result):
- AgentUpdate
tempacks = packacks() del ack_need_list[0:] if tempacks == "": flags = 0x00 else: flags = 0x10
#print "tempacks is:", ByteToHex(tempacks) packed_data_header = pack('>BLB', flags,currentsequence,0x00) packed_data_message_ID = pack('>B',0x04) packed_data_ID = uuid.UUID(result["agent_id"]).bytes + uuid.UUID(result["session_id"]).bytes packed_data_QuatRots = pack('>ffff', 0.0,0.0,0.0,0.0)+pack('>ffff', 0.0,0.0,0.0,0.0) packed_data_State = pack('>B', 0x00) packed_data_Camera = pack('>fff', 0.0,0.0,0.0)+pack('>fff', 0.0,0.0,0.0)+pack('>fff', 0.0,0.0,0.0)+pack('>fff', 0.0,0.0,0.0) packed_data_Flags = pack('>fLB', 0.0,0x00,0x00)
encoded_packed_data = zero_encode(packed_data_message_ID+packed_data_ID+packed_data_QuatRots+packed_data_State+packed_data_Camera+packed_data_Flags)
packed_data = packed_data_header + encoded_packed_data+tempacks
# print "sending AgentUpdate to server",ByteToHex(packed_data_header+zero_decode(encoded_packed_data)+ tempacks) sock.sendto(packed_data, (host, port)) return
def establishpresence(host, port, circuit_code):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- Sending packet UseCircuitCode <-- Inits the connection to the sim.
data = pack('>BLBL',0x00,0x01,00,0xffff0003) + pack('<L',circuit_code) + uuid.UUID(result["session_id"]).bytes+uuid.UUID(result["agent_id"]).bytes sock.sendto(data, (host, port))
- ISending packet CompleteAgentMovement <-- establishes the agent's presence
data = pack('>BLBL',0x00,0x02,00,0xffff00f9) + uuid.UUID(result["agent_id"]).bytes + uuid.UUID(result["session_id"]).bytes + pack('<L', circuit_code) sock.sendto(data, (host, port))
sendAgentUpdate(sock, port, host, 3, result)
buf = 100 i = 0 trusted_count = 0 ackable = 0 trusted_and_ackable = 0 ack_need_list_changed = False seqnum = 3 while 1: if ack_need_list_changed: ack_need_list_changed = False seqnum = seqnum + 1 sendAgentUpdate(sock, port, host, seqnum, result) #sendacks() i = i + 1 data,addr = sock.recvfrom(buf) if not data: print "Client has exited!" break else: test = ByteToHex(data).split() #print test ID = data[6:12] #print "ID =", ByteToHex(ID) if (ord(data[0])&0x80): ID = zero_decode_ID(data[6:12]) #print "ID =", ByteToHex(ID) #print "ID =", unpack(">L", ID[:4]) if ID[0] == '\xFF': if ID[1] == '\xFF': if ID[2] == '\xFF': myentry = mypacketdictionary[("Fixed" , int("0x"+ByteToHex(ID[2:4]).replace(' ', ),16))] if (ord(data[0])&0x40): scheduleacknowledgemessage(data); ack_need_list_changed = True print "Message #", i,"Flags: 0x" + test[0], myentry, "sequence #", unpack(">L",data[1:5]), "ack needed" #if myentry[1] == "Trusted": trusted_count = trusted_count +1;print "number of trusted messages =", trusted_count #if (ord(data[0])&0x40) and (myentry[1] == "Trusted"): trusted_and_ackable = trusted_and_ackable + 1; print "trusted_and_ackable =", trusted_and_ackable #if (ord(data[0])&0x40): ackable = ackable + 1; print "number of ackable messages = ", ackable else: myentry = mypacketdictionary[("Low",int("0x"+ByteToHex(ID[2:4]).replace(' ', ),16))] if (ord(data[0])&0x40): scheduleacknowledgemessage(data); ack_need_list_changed = True print "Message #", i,"Flags: 0x" + test[0], myentry, "sequence #", unpack(">L",data[1:5]) #if myentry[1] == "Trusted": trusted_count = trusted_count +1;print "number of trusted messages =", trusted_count #if (ord(data[0])&0x40) and (myentry[1] == "Trusted"): trusted_and_ackable = trusted_and_ackable + 1; print "trusted_and_ackable =", trusted_and_ackable #if (ord(data[0])&0x40): ackable = ackable + 1; print "number of ackable messages = ", ackable else: myentry = mypacketdictionary[("Medium", int("0x"+ByteToHex(ID[1:2]).replace(' ', ),16))] if (ord(data[0])&0x40): scheduleacknowledgemessage(data); ack_need_list_changed = True print "Message #", i,"Flags: 0x" + test[0], myentry, "sequence #", unpack(">L",data[1:5]) #if myentry[1] == "Trusted": trusted_count = trusted_count +1;print "number of trusted messages =", trusted_count #if (ord(data[0])&0x40) and (myentry[1] == "Trusted"): trusted_and_ackable = trusted_and_ackable + 1; print "trusted_and_ackable =", trusted_and_ackable #if (ord(data[0])&0x40): ackable = ackable + 1; print "number of ackable messages = ", ackable else: myentry = mypacketdictionary[("High", int("0x"+ByteToHex(ID[0]), 16))] if (ord(data[0])&0x40): scheduleacknowledgemessage(data); ack_need_list_changed = True print "Message #", i,"Flags: 0x" + test[0], myentry, "sequence #", unpack(">L",data[1:5]) #if myentry[1] == "Trusted": trusted_count = trusted_count +1;print "number of trusted messages =", trusted_count #if (ord(data[0])&0x40) and (myentry[1] == "Trusted"): trusted_and_ackable = trusted_and_ackable + 1; print "trusted_and_ackable =", trusted_and_ackable #if (ord(data[0])&0x40): ackable = ackable + 1; print "number of ackable messages = ", ackable sock.close() print "final number of trusted messages =", trusted_count return
result = login("first", "last", "password", MAC)
mypacketdictionary = makepacketdict()
myhost = result["sim_ip"] myport = result["sim_port"] mycircuit_code = result["circuit_code"]
establishpresence(myhost, myport, mycircuit_code)
- cap_out = get_caps(result,"seed_capability", ["ChatSessionRequest"])
</python>