Discussion:
[Pyogp] Example loop
Christian Scholz
2008-08-05 22:04:12 UTC
Permalink
Hi!

I was going through legacy-login.py today and tried to convert it into
some example how a message system could be used. This is probably not how
the existing interface looks like right now but I tried to think of how I
personlly would use one. Of course this is not the best or only way and I
am also not sure in certain cases how to model it best. I especially
dislike that the Region object now has the agent id and not the agent.
But I guess we have to talk about the id and how this might look like in
a global virtual world anyway.

We maybe can use this as the start of some discussion. One issue might be
to get everything thread safe and be as stateless as possible.

The general idea here was to start with the central thing we have, a
Message. This might be put into a Packet which basically adds the header
and has some state about it. It might store whether it got an ack or not.
Then there is the event_queue which basically is the sim endpoint. It
stores socket etc. and knows about the next sequence number so you don't
have to. It might also know which packet needs acks and so on.
But this is state and thus problematic if you share this between threads.

But anyway, here is the example code:

def loopit(region):
# event_queue takes care of sequence numbers etc. This is it's state.
event_queue = UDPEventQueue(region)
#Alternative: udpeventqueue = IUDPEventQueue(region)

# send UseCircuitCode to sim (region object has everything)
# it also sends the CompleteAgentMovement
event_queue.init()

# now we need to send an AgentUpdate packet
# we do it the raw way here:


message = IAgentUpdateMessage(event_queue) # get the message
# agent_id, session_id will be put in automatically as well
# as sensible defaults for these properties so you don't have
# to give them all. Here they are as an example though,
# I am not sure if this needs to give the types already, we might
# give tuples etc. and convert it during the packing maybe.
# some flags might also be modelled higher level like
# message.flag_whatever = True
# but for this one would need to know more about them ;-)
message.body_rotation = Vector4(0,0,0,0)
message.head_rotation = Vector4(0,0,0,0)
message.state(0)
message.camera_center = Vector3(0,0,0)
message.camera_at_axis = Vector3(0,0,0)
message.camera_left_axis = Vector3(0,0,0)
message.camera_up_axis = Vector3(0,0,0)
message.far = F32(256)
message.control_flags = U32(0)
message.flags = U8(0)

# now we need to put this message into a packet:
packet = IPacket(message)
# this will automatically put in message type and sequence
# number which can be obtained via message -> event_queue

"""
The original code for this:

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)
"""

# it makes sense to actually send the packet.
# we can maybe do it like this as the event_queue is known:
packet.send()

# or we can do it like this:
event_queue.send(packet)

# without too much ZCA we can maybe also do the above like follows:
message = AgentUpdate(far=512) # fill in message details
packet = Packet(message) # create a packet out of this
event_queue.send(packet) # send it to the sim

# in this case the send method can only add sequence number etc.
# as it's the only instance which knows about it.
# We can implement it like this though:
def send(self, packet):
"""send a funky packet"""
packet.sequence_number = self.sequence_number
data = packet.serialize() # or ISerialization(packet).serialize()
self.sock.sendto(data, self.address)

# now we need to send a NameRequest, the original code is:
"""
packed_data = ""
fix_ID = int("0xffff0000",16)+ 235
data_header = pack('>BLB', 0x00,currentsequence,0x00)


for i in range(len(aUUID)):
packed_data = packed_data+uuid.UUID(aUUID[i]).bytes

packed_data = data_header + pack("L",fix_ID) + pack(">B",len(aUUID))
+ packed_data

sock.sendto(packed_data, (host, port))
"""

# We can write it as:
message = NameRequestMessage(uuids=[region.agent_id,])
# region.agent_id is what we have but it's not nice looking as it
# should be agent.id so this needs thinking to be clean. Maybe it
# even needs thinking inside the protocol ;-)
# In this case it's also not a direct mapping from message to message
# object as it needs to deal with variable blocks in this case.

packet = Packet(message)
event_queue.send(packet)

# now let's wait for packets
while 1:
# we might need a different method here as we might get
# events from the outside to send some packets.
# Then again there should be enough packets coming in to
# not endlessly sit in this read_packet() call.
packet = event_queue.read_packet()
message = packet.message
message_id = message.id
# get some handler for handling this lovely message
handlers = getUtilitiesFor(IMessageHandler, name=str(message_id))
for handler in handlers:
# we give it the message of course but also the event_queue
# so it maybe can send other packets out.
handler.handle(event_queue, message)

# now do some bookkeeping like acking messages etc.
# actually this could also be done in read_packet maybe

# we might need a way to get out of this loop.















"""

ORIGINAL 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)
aUUID = [result["agent_id"]]
sendUUIDNameRequest(sock, port, host, 4,aUUID)
#

buf = 100
i = 0
trusted_count = 0
ackable = 0
trusted_and_ackable = 0
ack_need_list_changed = False
seqnum = 5
lastPingSent = 0
trusted = 0
while 1:
if ack_need_list_changed:
ack_need_list_changed = False
seqnum = seqnum + 1
sendPacketAck(sock, port, host,seqnum)
#sendAgentUpdate(sock, port, host, seqnum, result)
seqnum += 1
#sendacks()
i = i + 1
data,addr = sock.recvfrom(buf)
t = datetime.now()
t.strftime("%H:%M:%S")
"""
Tess Chu
2008-08-05 22:21:36 UTC
Permalink
Gah! Zero and I just went through OGP to restructure it and removed the
entire Legacy Login section of the doc! :( I'm sorry for not speaking
up earlier. It no longer needs to be tested.

Tess
Post by Christian Scholz
Hi!
I was going through legacy-login.py today and tried to convert it into
some example how a message system could be used. This is probably not how
the existing interface looks like right now but I tried to think of how I
personlly would use one. Of course this is not the best or only way and I
am also not sure in certain cases how to model it best. I especially
dislike that the Region object now has the agent id and not the agent.
But I guess we have to talk about the id and how this might look like in
a global virtual world anyway.
We maybe can use this as the start of some discussion. One issue might be
to get everything thread safe and be as stateless as possible.
The general idea here was to start with the central thing we have, a
Message. This might be put into a Packet which basically adds the header
and has some state about it. It might store whether it got an ack or not.
Then there is the event_queue which basically is the sim endpoint. It
stores socket etc. and knows about the next sequence number so you don't
have to. It might also know which packet needs acks and so on.
But this is state and thus problematic if you share this between threads.
# event_queue takes care of sequence numbers etc. This is it's state.
event_queue = UDPEventQueue(region)
#Alternative: udpeventqueue = IUDPEventQueue(region)
# send UseCircuitCode to sim (region object has everything)
# it also sends the CompleteAgentMovement
event_queue.init()
# now we need to send an AgentUpdate packet
message = IAgentUpdateMessage(event_queue) # get the message
# agent_id, session_id will be put in automatically as well
# as sensible defaults for these properties so you don't have
# to give them all. Here they are as an example though,
# I am not sure if this needs to give the types already, we might
# give tuples etc. and convert it during the packing maybe.
# some flags might also be modelled higher level like
# message.flag_whatever = True
# but for this one would need to know more about them ;-)
message.body_rotation = Vector4(0,0,0,0)
message.head_rotation = Vector4(0,0,0,0)
message.state(0)
message.camera_center = Vector3(0,0,0)
message.camera_at_axis = Vector3(0,0,0)
message.camera_left_axis = Vector3(0,0,0)
message.camera_up_axis = Vector3(0,0,0)
message.far = F32(256)
message.control_flags = U32(0)
message.flags = U8(0)
packet = IPacket(message)
# this will automatically put in message type and sequence
# number which can be obtained via message -> event_queue
"""
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)
"""
# it makes sense to actually send the packet.
packet.send()
event_queue.send(packet)
message = AgentUpdate(far=512) # fill in message details
packet = Packet(message) # create a packet out of this
event_queue.send(packet) # send it to the sim
# in this case the send method can only add sequence number etc.
# as it's the only instance which knows about it.
"""send a funky packet"""
packet.sequence_number = self.sequence_number
data = packet.serialize() # or ISerialization(packet).serialize()
self.sock.sendto(data, self.address)
"""
packed_data = ""
fix_ID = int("0xffff0000",16)+ 235
data_header = pack('>BLB', 0x00,currentsequence,0x00)
packed_data = packed_data+uuid.UUID(aUUID[i]).bytes
packed_data = data_header + pack("L",fix_ID) + pack(">B",len(aUUID))
+ packed_data
sock.sendto(packed_data, (host, port))
"""
message = NameRequestMessage(uuids=[region.agent_id,])
# region.agent_id is what we have but it's not nice looking as it
# should be agent.id so this needs thinking to be clean. Maybe it
# even needs thinking inside the protocol ;-)
# In this case it's also not a direct mapping from message to message
# object as it needs to deal with variable blocks in this case.
packet = Packet(message)
event_queue.send(packet)
# now let's wait for packets
# we might need a different method here as we might get
# events from the outside to send some packets.
# Then again there should be enough packets coming in to
# not endlessly sit in this read_packet() call.
packet = event_queue.read_packet()
message = packet.message
message_id = message.id
# get some handler for handling this lovely message
handlers = getUtilitiesFor(IMessageHandler, name=str(message_id))
# we give it the message of course but also the event_queue
# so it maybe can send other packets out.
handler.handle(event_queue, message)
# now do some bookkeeping like acking messages etc.
# actually this could also be done in read_packet maybe
# we might need a way to get out of this loop.
"""
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)
aUUID = [result["agent_id"]]
sendUUIDNameRequest(sock, port, host, 4,aUUID)
#
buf = 100
i = 0
trusted_count = 0
ackable = 0
trusted_and_ackable = 0
ack_need_list_changed = False
seqnum = 5
lastPingSent = 0
trusted = 0
ack_need_list_changed = False
seqnum = seqnum + 1
sendPacketAck(sock, port, host,seqnum)
#sendAgentUpdate(sock, port, host, seqnum, result)
seqnum += 1
#sendacks()
i = i + 1
data,addr = sock.recvfrom(buf)
t = datetime.now()
t.strftime("%H:%M:%S")
"""
_______________________________________________
https://lists.secondlife.com/cgi-bin/mailman/listinfo/pyogp
Lawson English
2008-08-05 22:59:52 UTC
Permalink
Post by Tess Chu
Gah! Zero and I just went through OGP to restructure it and removed
the entire Legacy Login section of the doc! :( I'm sorry for not
speaking up earlier. It no longer needs to be tested.
I think we're at cross-purposes here. There's no way pyogp can be useful
for non LL purposes until the OGP transformation is complete unless
people can use it as the starting point for creating lightweight clients
that work with legacy protocols, including logins.

Certainly, I don't expect LL to do the work on this, but don't assume
that its not something desired by the greater SL community.


Lawson
Lawson English
2008-08-06 02:14:17 UTC
Permalink
Post by Lawson English
Post by Tess Chu
Gah! Zero and I just went through OGP to restructure it and removed
the entire Legacy Login section of the doc! :( I'm sorry for not
speaking up earlier. It no longer needs to be tested.
I think we're at cross-purposes here. There's no way pyogp can be
useful for non LL purposes until the OGP transformation is complete
unless people can use it as the starting point for creating
lightweight clients that work with legacy protocols, including logins.
Certainly, I don't expect LL to do the work on this, but don't assume
that its not something desired by the greater SL community.
Ah just realized you were talking about the official "Legacy Login" of
OGP, not the legacy [old school] login, the support for which hasn't
been written yet anyway, at least in pyogp.


Lawson
Christian Scholz
2008-08-06 07:51:44 UTC
Permalink
Hi!

I am not sure what you all now mean by "legacy login" ;-)
The script I mentioned was just cally pyogp-legacy.py for whatever
reason. It used the new OGP login mechanism though and then jumps into
the UDP loop. So it's basically what we need to know right now.
The login part is not included in my example, it starts after what the
example login in pyogp is doing right now.

But I will have a look at the new specs. That being said it would maybe
also be good to communicate more about the spec over e.g. the gridnauts
mailing list.

-- Christian
Post by Lawson English
Post by Lawson English
Post by Tess Chu
Gah! Zero and I just went through OGP to restructure it and removed
the entire Legacy Login section of the doc! :( I'm sorry for not
speaking up earlier. It no longer needs to be tested.
I think we're at cross-purposes here. There's no way pyogp can be
useful for non LL purposes until the OGP transformation is complete
unless people can use it as the starting point for creating
lightweight clients that work with legacy protocols, including logins.
Certainly, I don't expect LL to do the work on this, but don't assume
that its not something desired by the greater SL community.
Ah just realized you were talking about the official "Legacy Login" of
OGP, not the legacy [old school] login, the support for which hasn't
been written yet anyway, at least in pyogp.
Lawson
_______________________________________________
https://lists.secondlife.com/cgi-bin/mailman/listinfo/pyogp
--
Christian Scholz Homepage: http://comlounge.net
COM.lounge blog: http://mrtopf.de/blog
Luetticher Strasse 10 Skype: HerrTopf
52064 Aachen Video Blog: http://comlounge.tv
Tel: +49 241 400 730 0 E-Mail ***@comlounge.net
Fax: +49 241 979 00 850 IRC: MrTopf, Tao_T

neue Show: TOPFt?glich (http://mrtopf.de/blog/category/topf-taglich/)
locklainn
2008-08-06 14:27:45 UTC
Permalink
Post by Christian Scholz
The general idea here was to start with the central thing we have, a
Message. This might be put into a Packet which basically adds the header
and has some state about it. It might store whether it got an ack or not.
Yes, we currently have a Packet. It keeps track of the host that sent it and on what socket, the number of retries it has left before it should be rejected, and its expiration time. Of course, it also has the message in it. It doesn't keep track of whether or not it was acked, because when a packet is acked there is no reason to keep track of it.
Post by Christian Scholz
Then there is the event_queue which basically is the sim endpoint. It
stores socket etc. and knows about the next sequence number so you don't
have to. It might also know which packet needs acks and so on.
But this is state and thus problematic if you share this between threads.
The event_queue sounds like what we call a Circuit. It keeps track of
the next packet ID (sequence number) that will be sent over it, knows
which packets going over the circuit need acks, and which IT needs to
ack, etc. BTW - there is also a CircuitManager which can store a bunch
of circuits and perform some operations on them.
Post by Christian Scholz
# event_queue takes care of sequence numbers etc. This is it's state.
event_queue = UDPEventQueue(region)
#Alternative: udpeventqueue = IUDPEventQueue(region)
# send UseCircuitCode to sim (region object has everything)
# it also sends the CompleteAgentMovement
event_queue.init()
# now we need to send an AgentUpdate packet
message = IAgentUpdateMessage(event_queue) # get the message
# agent_id, session_id will be put in automatically as well
# as sensible defaults for these properties so you don't have
# to give them all. Here they are as an example though,
# I am not sure if this needs to give the types already, we might
# give tuples etc. and convert it during the packing maybe.
# some flags might also be modelled higher level like
# message.flag_whatever = True
# but for this one would need to know more about them ;-)
message.body_rotation = Vector4(0,0,0,0)
message.head_rotation = Vector4(0,0,0,0)
message.state(0)
message.camera_center = Vector3(0,0,0)
message.camera_at_axis = Vector3(0,0,0)
message.camera_left_axis = Vector3(0,0,0)
message.camera_up_axis = Vector3(0,0,0)
message.far = F32(256)
message.control_flags = U32(0)
message.flags = U8(0)
packet = IPacket(message)
# this will automatically put in message type and sequence
# number which can be obtained via message -> event_queue
"""
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)
"""
# it makes sense to actually send the packet.
packet.send()
event_queue.send(packet)
message = AgentUpdate(far=512) # fill in message details
packet = Packet(message) # create a packet out of this
event_queue.send(packet) # send it to the sim
# in this case the send method can only add sequence number etc.
# as it's the only instance which knows about it.
"""send a funky packet"""
packet.sequence_number = self.sequence_number
data = packet.serialize() # or ISerialization(packet).serialize()
self.sock.sendto(data, self.address)
"""
packed_data = ""
fix_ID = int("0xffff0000",16)+ 235
data_header = pack('>BLB', 0x00,currentsequence,0x00)
packed_data = packed_data+uuid.UUID(aUUID[i]).bytes
packed_data = data_header + pack("L",fix_ID) + pack(">B",len(aUUID))
+ packed_data
sock.sendto(packed_data, (host, port))
"""
message = NameRequestMessage(uuids=[region.agent_id,])
# region.agent_id is what we have but it's not nice looking as it
# should be agent.id so this needs thinking to be clean. Maybe it
# even needs thinking inside the protocol ;-)
# In this case it's also not a direct mapping from message to message
# object as it needs to deal with variable blocks in this case.
packet = Packet(message)
event_queue.send(packet)
# now let's wait for packets
# we might need a different method here as we might get
# events from the outside to send some packets.
# Then again there should be enough packets coming in to
# not endlessly sit in this read_packet() call.
packet = event_queue.read_packet()
message = packet.message
message_id = message.id
# get some handler for handling this lovely message
handlers = getUtilitiesFor(IMessageHandler, name=str(message_id))
# we give it the message of course but also the event_queue
# so it maybe can send other packets out.
handler.handle(event_queue, message)
# now do some bookkeeping like acking messages etc.
# actually this could also be done in read_packet maybe
# we might need a way to get out of this loop.
"""
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)
aUUID = [result["agent_id"]]
sendUUIDNameRequest(sock, port, host, 4,aUUID)
#
buf = 100
i = 0
trusted_count = 0
ackable = 0
trusted_and_ackable = 0
ack_need_list_changed = False
seqnum = 5
lastPingSent = 0
trusted = 0
ack_need_list_changed = False
seqnum = seqnum + 1
sendPacketAck(sock, port, host,seqnum)
#sendAgentUpdate(sock, port, host, seqnum, result)
seqnum += 1
#sendacks()
i = i + 1
data,addr = sock.recvfrom(buf)
t = datetime.now()
t.strftime("%H:%M:%S")
"""
_______________________________________________
https://lists.secondlife.com/cgi-bin/mailman/listinfo/pyogp
Loading...