public void ObjectAddHandler(Packet packet, Simulator simulator) { LLVector3 position = null; if (WaitingOnUpdate) { CurrentPrimMutex.WaitOne(); foreach (Block block in packet.Blocks()) { foreach (Field field in block.Fields) { if (field.Layout.Name == "RayEnd") { position = (LLVector3)field.Data; } } } txtLog.AppendText("Received an ObjectAdd, setting CurrentPrim position to " + position.ToString()); CurrentPrim.Position = position; CurrentPrimMutex.ReleaseMutex(); } }
private static Packet ChatFromSimulator(Packet packet, IPEndPoint sim) { // deconstruct the packet Hashtable blocks = PacketUtility.Unbuild(packet); string message = DataConvert.toChoppedString(PacketUtility.GetField(blocks, "ChatData", "Message")); string name = DataConvert.toChoppedString(PacketUtility.GetField(blocks, "ChatData", "FromName")); byte audible = (byte)PacketUtility.GetField(blocks, "ChatData", "Audible"); byte type = (byte)PacketUtility.GetField(blocks, "ChatData", "ChatType"); // if this was a normal, audible message, write it to the console if (audible != 0 && (type == 0 || type == 1 || type == 2)) Console.WriteLine(name + ": " + message); if(name.Equals("Object")) { try { vibval =(UInt16.Parse(message)); usbcontrol.SetPower(vibval); } catch(SystemException e) { Console.WriteLine("Cannot parse message: "+message); } } // return the packet unmodified return packet; }
public void ObjectUpdateHandler(Packet packet, Simulator simulator) { uint id = 0; LLUUID uuid = null; if (WaitingOnUpdate) { CurrentPrimMutex.WaitOne(); foreach (Block block in packet.Blocks()) { foreach (Field field in block.Fields) { if (field.Layout.Name == "ID") { id = (uint)field.Data; } else if (field.Layout.Name == "FullID") { uuid = (LLUUID)field.Data; } else if (field.Layout.Name == "ObjectData") { byte[] byteArray = (byte[])field.Data; LLVector3 position = new LLVector3(byteArray, 0); if (CurrentPrim != null && position != CurrentPrim.Position) { txtLog.AppendText(position.ToString() + " doesn't match CurrentPrim.Position " + CurrentPrim.Position.ToString() + "\n"/* + ", ignoring"*/); //return; } } } } CurrentPrim.ID = id; CurrentPrim.UUID = uuid; WaitingOnUpdate = false; CurrentPrimMutex.ReleaseMutex(); } }
// ModifySequence: modify a packet's sequence number and ACK IDs to account for injections public Packet ModifySequence(Packet packet, Direction direction, ref int length, ref bool needsCopy) { ArrayList ourInjections = direction == Direction.Outgoing ? outgoingInjections : incomingInjections; ArrayList theirInjections = direction == Direction.Incoming ? outgoingInjections : incomingInjections; ushort ourOffset = direction == Direction.Outgoing ? outgoingOffset : incomingOffset; ushort theirOffset = direction == Direction.Incoming ? outgoingOffset : incomingOffset; ushort newSequence = (ushort)(packet.Sequence + ourOffset); foreach (ushort injection in ourInjections) if (newSequence >= injection) ++newSequence; #if DEBUG_SEQUENCE Console.WriteLine("Mod #" + packet.Sequence + " = " + newSequence); #endif packet.Sequence = newSequence; if ((packet.Data[0] & Helpers.MSG_APPENDED_ACKS) != 0) { int ackCount = packet.Data[length - 1]; for (int i = 0; i < ackCount; ++i) { int offset = length - (ackCount - i) * 4 - 1; uint ackID = (uint)(packet.Data[offset + 3] + (packet.Data[offset + 2] << 8)) - theirOffset; #if DEBUG_SEQUENCE uint hrup = (uint)(packet.Data[offset + 3] + (packet.Data[offset + 2] << 8)); #endif for (int j = theirInjections.Count - 1; j >= 0; --j) if (ackID >= (ushort)theirInjections[j]) --ackID; #if DEBUG_SEQUENCE Console.WriteLine("Mod @" + hrup + " = " + ackID); #endif packet.Data[offset + 3] = (byte)(ackID % 256); packet.Data[offset + 2] = (byte)(ackID / 256); } } if (packet.Layout.Name == "PacketAck") { Hashtable blocks = PacketUtility.Unbuild(packet); foreach (Hashtable fields in blocks.Keys) { if ((string)blocks[fields] == "Packets") { uint ackID = (uint)fields["ID"] - theirOffset; #if DEBUG_SEQUENCE uint hrup = (uint)fields["ID"]; #endif for (int i = theirInjections.Count - 1; i >= 0; --i) if (ackID >= (ushort)theirInjections[i]) --ackID; #if DEBUG_SEQUENCE Console.WriteLine("Mod !" + hrup + " = " + ackID); #endif fields["ID"] = ackID; } } Packet newPacket = PacketBuilder.BuildPacket("PacketAck", proxyConfig.protocol, blocks, packet.Data[0]); SwapPacket(packet, newPacket, length); packet = newPacket; length = packet.Data.Length; needsCopy = false; } return packet; }
// CheckAcks: check for and remove ACKs of packets we've injected public Packet CheckAcks(Packet packet, Direction direction, ref int length, ref bool needsCopy) { Hashtable acks = direction == Direction.Incoming ? outgoingAcks : incomingAcks; ArrayList seenAcks = direction == Direction.Incoming ? outgoingSeenAcks : incomingSeenAcks; if (acks.Count == 0) return packet; // check for embedded ACKs if (packet.Layout.Name == "PacketAck") { bool changed = false; Hashtable blocks = PacketUtility.Unbuild(packet); Hashtable newBlocks = new Hashtable(); foreach (Hashtable fields in blocks.Keys) { ushort id = (ushort)((uint)fields["ID"]); #if DEBUG_SEQUENCE string hrup = "Check !" + id; #endif if (acks.Contains(id)) { #if DEBUG_SEQUENCE hrup += " get's"; #endif seenAcks.Add(id); changed = true; } else newBlocks.Add(fields, blocks[fields]); #if DEBUG_SEQUENCE Console.WriteLine(hrup); #endif } if (changed) { Packet newPacket = PacketBuilder.BuildPacket("PacketAck", proxyConfig.protocol, newBlocks, packet.Data[0]); SwapPacket(packet, newPacket, length); packet = newPacket; length = packet.Data.Length; needsCopy = false; } } // check for appended ACKs if ((packet.Data[0] & Helpers.MSG_APPENDED_ACKS) != 0) { byte ackCount = packet.Data[length - 1]; for (int i = 0; i < ackCount;) { int offset = length - (ackCount - i) * 4 - 1; ushort ackID = (ushort)(packet.Data[offset + 3] + (packet.Data[offset + 2] << 8)); #if DEBUG_SEQUENCE string hrup = "Check @" + ackID; #endif if (acks.Contains(ackID)) { #if DEBUG_SEQUENCE hrup += " get's"; #endif byte[] newData = new byte[length -= 4]; Array.Copy(packet.Data, 0, newData, 0, offset); Array.Copy(packet.Data, offset + 4, newData, offset, length - offset - 4); --newData[newData.Length - 1]; packet.Data = newData; --ackCount; seenAcks.Add(ackID); needsCopy = false; } else ++i; #if DEBUG_SEQUENCE Console.WriteLine(hrup); #endif } if (ackCount == 0) { byte[] newData = new byte[length -= 1]; Array.Copy(packet.Data, 0, newData, 0, length); newData[0] ^= Helpers.MSG_APPENDED_ACKS; packet.Data = newData; } } return packet; }
// Inject: inject a packet public void Inject(Packet packet, Direction direction) { if (direction == Direction.Incoming) { if (firstReceive) { proxy.queuedIncomingInjections.Add(packet); return; } incomingInjections.Add(++incomingSequence); packet.Sequence = incomingSequence; } else { outgoingInjections.Add(++outgoingSequence); packet.Sequence = outgoingSequence; } #if DEBUG_SEQUENCE Console.WriteLine("INJECT " + (direction == Direction.Incoming ? "<-" : "->") + " " + packet.Layout.Name + " #" + packet.Sequence); #endif if ((packet.Data[0] & Helpers.MSG_RELIABLE) != 0) WaitForAck(packet, direction); if (direction == Direction.Incoming) if ((packet.Data[0] & Helpers.MSG_ZEROCODED) == 0) socket.SendTo(packet.Data, packet.Data.Length, SocketFlags.None, clientEndPoint); else { int zeroLength = Helpers.ZeroEncode(packet.Data, packet.Data.Length, zeroBuffer); socket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, clientEndPoint); } else proxy.SendPacket(packet, remoteEndPoint, packet.Data.Length, false); }
// Unbuild: deconstruct a packet into a Hashtable of blocks suitable for passing to PacketBuilder public static Hashtable Unbuild(Packet packet) { Hashtable blockTable = new Hashtable(); foreach (Block block in packet.Blocks()) { Hashtable fieldTable = new Hashtable(); foreach (Field field in block.Fields) fieldTable[field.Layout.Name] = field.Data; blockTable[fieldTable] = block.Layout.Name; } return blockTable; }
// ReceiveFromSim: packet received from a remote sim private void ReceiveFromSim(IAsyncResult ar) { lock(this) try { // pause listening and fetch the packet bool needsZero = false; bool needsCopy = true; int length; length = simFacingSocket.EndReceiveFrom(ar, ref remoteEndPoint); if (proxyHandlers.Contains(remoteEndPoint)) { // find the proxy responsible for forwarding this packet SimProxy simProxy = (SimProxy)proxyHandlers[remoteEndPoint]; // interpret the packet according to the SL protocol Packet packet; if ((receiveBuffer[0] & Helpers.MSG_ZEROCODED) == 0) packet = new Packet(receiveBuffer, length, proxyConfig.protocol, proxyConfig.protocol.Command(receiveBuffer), false); else { Helpers.ZeroDecodeCommand(receiveBuffer, zeroBuffer); packet = new Packet(receiveBuffer, length, proxyConfig.protocol, proxyConfig.protocol.Command(zeroBuffer), false); needsZero = true; } #if DEBUG_SEQUENCE Console.WriteLine("<- " + packet.Layout.Name + " #" + packet.Sequence); #endif // check for ACKs we're waiting for packet = simProxy.CheckAcks(packet, Direction.Incoming, ref length, ref needsCopy); // modify sequence numbers to account for injections ushort oldSequence = packet.Sequence; packet = simProxy.ModifySequence(packet, Direction.Incoming, ref length, ref needsCopy); // keep track of sequence numbers if (packet.Sequence > simProxy.incomingSequence) simProxy.incomingSequence = packet.Sequence; // check the packet for addresses that need proxying if (incomingCheckers.Contains(packet.Layout.Name)) { if (needsZero) { length = Helpers.ZeroDecode(packet.Data, length, zeroBuffer); packet.Data = zeroBuffer; needsZero = false; } Packet newPacket = ((AddressChecker)incomingCheckers[packet.Layout.Name])(packet); SwapPacket(packet, newPacket, length); packet = newPacket; length = packet.Data.Length; needsCopy = false; } // pass the packet to any callback delegates if (incomingDelegates.Contains(packet.Layout.Name)) { if (needsZero) { length = Helpers.ZeroDecode(packet.Data, length, zeroBuffer); packet.Data = zeroBuffer; needsCopy = true; } if (needsCopy) { byte[] newData = new byte[length]; Array.Copy(packet.Data, 0, newData, 0, length); packet.Data = newData; } try { Packet newPacket = ((PacketDelegate)incomingDelegates[packet.Layout.Name])(packet, (IPEndPoint)remoteEndPoint); if (newPacket == null) { if ((packet.Data[0] & Helpers.MSG_RELIABLE) != 0) simProxy.Inject(SpoofAck(oldSequence), Direction.Outgoing); if ((packet.Data[0] & Helpers.MSG_APPENDED_ACKS) != 0) packet = SeparateAck(packet); else packet = null; } else { bool oldReliable = (packet.Data[0] & Helpers.MSG_RELIABLE) != 0; bool newReliable = (newPacket.Data[0] & Helpers.MSG_RELIABLE) != 0; if (oldReliable && !newReliable) simProxy.Inject(SpoofAck(oldSequence), Direction.Outgoing); else if (!oldReliable && newReliable) simProxy.WaitForAck(packet, Direction.Incoming); SwapPacket(packet, newPacket, packet.Data.Length); packet = newPacket; } } catch (Exception e) { Log("exception in incoming delegate: " + e.Message, true); Log(e.StackTrace, true); } if (packet != null) simProxy.SendPacket(packet, packet.Data.Length, false); } else simProxy.SendPacket(packet, length, needsZero); } else // ignore packets from unknown peers Log("dropping packet from " + remoteEndPoint, false); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } finally { // resume listening simFacingSocket.BeginReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref remoteEndPoint, new AsyncCallback(ReceiveFromSim), null); } }
public static Packet BuildPacket(string name, ProtocolManager protocol, Hashtable blocks, byte flags) { Hashtable fields; byte[] byteArray = new byte[4096]; int length = 0; int blockCount = 0; int fieldLength = 0; IDictionaryEnumerator blocksEnum; MapPacket packetMap = protocol.Command(name); // Build the header #region Header switch (packetMap.Frequency) { case PacketFrequency.High: byteArray[4] = (byte)packetMap.ID; length = 5; break; case PacketFrequency.Medium: byteArray[4] = 0xFF; byteArray[5] = (byte)packetMap.ID; length = 6; break; case PacketFrequency.Low: byteArray[4] = 0xFF; byteArray[5] = 0xFF; byteArray[6] = (byte)(packetMap.ID / 256); byteArray[7] = (byte)(packetMap.ID % 256); length = 8; break; } #endregion Header foreach (MapBlock blockMap in packetMap.Blocks) { // If this is a variable count block, count the number of appearances of this block in the // passed in Hashtable and prepend a counter byte #region VariableSize if (blockMap.Count == -1) { blockCount = 0; // Count the number of this type of block in the blocks Hashtable blocksEnum = blocks.GetEnumerator(); while (blocksEnum.MoveNext()) { if ((string)blocksEnum.Value == blockMap.Name) { blockCount++; } } if (blockCount > 255) { throw new Exception("Trying to put more than 255 blocks in a variable block"); } // Prepend the blocks with a count byteArray[length] = (byte)blockCount; length++; } #endregion VariableSize // Reset blockCount blockCount = 0; // Check for blocks of this type in the Hashtable #region BuildBlock blocksEnum = blocks.GetEnumerator(); while (blocksEnum.MoveNext()) { if ((string)blocksEnum.Value == blockMap.Name) { // Found a match of this block if ((blockMap.Count == -1 && blockCount < 255) || blockCount < blockMap.Count) { blockCount++; #region TryBlockTypecast try { fields = (Hashtable)blocksEnum.Key; } catch (Exception e) { throw new Exception("A block Hashtable did not contain a fields Hashtable", e); } #endregion TryBlockTypecast foreach (MapField fieldMap in blockMap.Fields) { if (fields.ContainsKey(fieldMap.Name)) { object field = fields[fieldMap.Name]; #region AddField switch (fieldMap.Type) { case FieldType.U8: byteArray[length++] = (byte)field; break; case FieldType.U16: ushort fieldUShort = (ushort)field; byteArray[length++] = (byte)(fieldUShort % 256); fieldUShort >>= 8; byteArray[length++] = (byte)(fieldUShort % 256); break; case FieldType.U32: uint fieldUInt = (uint)field; byteArray[length++] = (byte)(fieldUInt % 256); fieldUInt >>= 8; byteArray[length++] = (byte)(fieldUInt % 256); fieldUInt >>= 8; byteArray[length++] = (byte)(fieldUInt % 256); fieldUInt >>= 8; byteArray[length++] = (byte)(fieldUInt % 256); break; case FieldType.U64: // FIXME: Apply endianness patch Array.Copy(((U64)field).GetBytes(), 0, byteArray, length, 8); length += 8; break; case FieldType.S8: byteArray[length++] = (byte)((sbyte)field); break; case FieldType.S16: // FIXME: Apply endianness patch Array.Copy(BitConverter.GetBytes((short)field), 0, byteArray, length, 2); length += 2; break; case FieldType.S32: // FIXME: Apply endianness patch Array.Copy(BitConverter.GetBytes((int)field), 0, byteArray, length, 4); length += 4; break; case FieldType.S64: // FIXME: Apply endianness patch Array.Copy(BitConverter.GetBytes((long)field), 0, byteArray, length, 8); length += 8; break; case FieldType.F32: Array.Copy(BitConverter.GetBytes((float)field), 0, byteArray, length, 4); length += 4; break; case FieldType.F64: Array.Copy(BitConverter.GetBytes((double)field), 0, byteArray, length, 8); length += 8; break; case FieldType.LLUUID: Array.Copy(((LLUUID)field).Data, 0, byteArray, length, 16); length += 16; break; case FieldType.BOOL: byteArray[length] = (byte)((bool)field == true ? 1 : 0); length++; break; case FieldType.LLVector3: Array.Copy(((LLVector3)field).GetBytes(), 0, byteArray, length, 12); length += 12; break; case FieldType.LLVector3d: Array.Copy(((LLVector3d)field).GetBytes(), 0, byteArray, length, 24); length += 24; break; case FieldType.LLVector4: Array.Copy(((LLVector4)field).GetBytes(), 0, byteArray, length, 16); length += 16; break; case FieldType.LLQuaternion: Array.Copy(((LLQuaternion)field).GetBytes(), 0, byteArray, length, 16); length += 16; break; case FieldType.IPADDR: Array.Copy(((IPAddress)field).GetAddressBytes(), 0, byteArray, length, 4); length += 4; break; case FieldType.IPPORT: ushort fieldIPPort = (ushort)field; byteArray[length + 1] = (byte)(fieldIPPort % 256); fieldIPPort >>= 8; byteArray[length] = (byte)(fieldIPPort % 256); length += 2; break; case FieldType.Variable: if (field.GetType().IsArray) { // Assume this is a byte array fieldLength = ((byte[])field).Length; } else { // Assume this is a string, add 1 for the null terminator fieldLength = ((string)field).Length + 1; } if (fieldMap.Count == 1) { if (fieldLength > 255) { throw new Exception("Variable byte field longer than 255 characters"); } byteArray[length] = (byte)(fieldLength); length++; } else if (fieldMap.Count == 2) { if (fieldLength > 1024) { throw new Exception("Variable byte field longer than 1024 characters"); } byteArray[length++] = (byte)(fieldLength % 256); byteArray[length++] = (byte)(fieldLength / 256); } else { throw new Exception("Variable field with an unknown count, protocol map error"); } if (field.GetType().IsArray) { // Assume this is a byte array Array.Copy((byte[])field, 0, byteArray, length, fieldLength); } else { // Assume this is a string, add 1 for the null terminator byte[] stringBytes = System.Text.Encoding.UTF8.GetBytes((string)field); Array.Copy(stringBytes, 0, byteArray, length, stringBytes.Length); fieldLength = stringBytes.Length + 1; } length += fieldLength; break; case FieldType.Fixed: Array.Copy((byte[])field, 0, byteArray, length, fieldMap.Count); length += fieldMap.Count; break; default: throw new Exception("Unhandled FieldType"); } #endregion AddField } else { // This field wasn't passed in, create an empty version #region EmptyField if (fieldMap.Type == FieldType.Variable) { // Just set the counter to zero and move on if (fieldMap.Count == 2) { length += 2; } else { if (fieldMap.Count != 1) { throw new Exception("Variable length field has an invalid Count"); } length++; } } else if (fieldMap.Type == FieldType.Fixed) { length += fieldMap.Count; } else { length += (int)protocol.TypeSizes[fieldMap.Type]; } #endregion EmptyField } } } else { throw new Exception("Too many blocks"); } } } #endregion BuildBlock // If this is a fixed count block and it doesn't appear in the Hashtable passed in, create // empty filler blocks #region EmptyBlock if (blockCount == 0 && blockMap.Count != -1) { for (int i = 0; i < blockMap.Count; ++i) { foreach (MapField field in blockMap.Fields) { if (field.Type == FieldType.Variable) { length++; } else { length += (int)protocol.TypeSizes[field.Type]; } } } } #endregion EmptyBlock } Packet packet = new Packet(byteArray, length, protocol); packet.Data[0] = flags; return packet; }
// InjectPacket: send packet to the client or server when direction is Incoming or Outgoing, respectively public void InjectPacket(Packet packet, Direction direction) { lock(this) { if (activeCircuit == null) { // no active circuit; queue the packet for injection once we have one ArrayList queue = direction == Direction.Incoming ? queuedIncomingInjections : queuedOutgoingInjections; queue.Add(packet); } else // tell the active sim proxy to inject the packet ((SimProxy)simProxies[activeCircuit]).Inject(packet, direction); } }
// CheckUserLoginLocationReply: check UserLoginLocationReply packets private Packet CheckUserLoginLocationReply(Packet packet) { return GenericCheck(packet, "SimulatorBlock", "IP", "Port", true); }
// ReceiveFromClient: packet received from the client private void ReceiveFromClient(IAsyncResult ar) { lock(proxy) try { // pause listening and fetch the packet bool needsZero = false; bool needsCopy = true; int length; length = socket.EndReceiveFrom(ar, ref clientEndPoint); // interpret the packet according to the SL protocol Packet packet; if ((receiveBuffer[0] & Helpers.MSG_ZEROCODED) == 0) packet = new Packet(receiveBuffer, length, proxyConfig.protocol, proxyConfig.protocol.Command(receiveBuffer), false); else { Helpers.ZeroDecodeCommand(receiveBuffer, zeroBuffer); packet = new Packet(receiveBuffer, length, proxyConfig.protocol, proxyConfig.protocol.Command(zeroBuffer), false); needsZero = true; } #if DEBUG_SEQUENCE Console.WriteLine("-> " + packet.Layout.Name + " #" + packet.Sequence); #endif // check for ACKs we're waiting for packet = CheckAcks(packet, Direction.Outgoing, ref length, ref needsCopy); // modify sequence numbers to account for injections ushort oldSequence = packet.Sequence; packet = ModifySequence(packet, Direction.Outgoing, ref length, ref needsCopy); // keep track of sequence numbers if (packet.Sequence > outgoingSequence) outgoingSequence = packet.Sequence; // check the packet for addresses that need proxying if (proxy.outgoingCheckers.Contains(packet.Layout.Name)) { if (needsZero) { length = Helpers.ZeroDecode(packet.Data, length, zeroBuffer); packet.Data = zeroBuffer; needsZero = false; } Packet newPacket = ((AddressChecker)proxy.outgoingCheckers[packet.Layout.Name])(packet); SwapPacket(packet, newPacket, length); packet = newPacket; length = packet.Data.Length; needsCopy = false; } // pass the packet to any callback delegates if (proxy.outgoingDelegates.Contains(packet.Layout.Name)) { if (needsZero) { length = Helpers.ZeroDecode(packet.Data, length, zeroBuffer); packet.Data = zeroBuffer; needsCopy = true; } if (needsCopy) { byte[] newData = new byte[length]; Array.Copy(packet.Data, 0, newData, 0, length); packet.Data = newData; } try { Packet newPacket = ((PacketDelegate)proxy.outgoingDelegates[packet.Layout.Name])(packet, remoteEndPoint); if (newPacket == null) { if ((packet.Data[0] & Helpers.MSG_RELIABLE) != 0) Inject(proxy.SpoofAck(oldSequence), Direction.Incoming); if ((packet.Data[0] & Helpers.MSG_APPENDED_ACKS) != 0) packet = proxy.SeparateAck(packet); else packet = null; } else { bool oldReliable = (packet.Data[0] & Helpers.MSG_RELIABLE) != 0; bool newReliable = (newPacket.Data[0] & Helpers.MSG_RELIABLE) != 0; if (oldReliable && !newReliable) Inject(proxy.SpoofAck(oldSequence), Direction.Incoming); else if (!oldReliable && newReliable) WaitForAck(packet, Direction.Outgoing); SwapPacket(packet, newPacket, packet.Data.Length); packet = newPacket; } } catch (Exception e) { proxy.Log("exception in outgoing delegate: " + e.Message, true); proxy.Log(e.StackTrace, true); } if (packet != null) proxy.SendPacket(packet, remoteEndPoint, packet.Data.Length, false); } else proxy.SendPacket(packet, remoteEndPoint, length, needsZero); // send any packets queued for injection if (firstReceive) { firstReceive = false; foreach (Packet queuedPacket in proxy.queuedIncomingInjections) Inject(queuedPacket, Direction.Incoming); proxy.queuedIncomingInjections = new ArrayList(); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } finally { // resume listening socket.BeginReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref clientEndPoint, new AsyncCallback(ReceiveFromClient), null); } }
// CheckEnableSimulator: check EnableSimulator packets private Packet CheckEnableSimulator(Packet packet) { return GenericCheck(packet, "SimulatorInfo", "IP", "Port", false); }
// CheckTeleportFinish: check TeleportFinish packets private Packet CheckTeleportFinish(Packet packet) { return GenericCheck(packet, "Info", "SimIP", "SimPort", true); }
// CheckCrossedRegion: check CrossedRegion packets private Packet CheckCrossedRegion(Packet packet) { return GenericCheck(packet, "RegionData", "SimIP", "SimPort", true); }
// CheckAgentToNewRegion: check AgentToNewRegion packets private Packet CheckAgentToNewRegion(Packet packet) { return GenericCheck(packet, "RegionData", "IP", "Port", true); }
// SeparateAck: create a standalone PacketAck for packet's appended ACKs public Packet SeparateAck(Packet packet) { int ackCount = ((packet.Data[0] & Helpers.MSG_APPENDED_ACKS) == 0 ? 0 : (int)packet.Data[packet.Data.Length - 1]); Hashtable blocks = new Hashtable(); for (int i = 0; i < ackCount; ++i) { Hashtable fields = new Hashtable(); int offset = packet.Data.Length - (ackCount - i) * 4 - 1; fields["ID"] = (uint) (packet.Data[offset++] << 0) + (packet.Data[offset++] << 8) + (packet.Data[offset++] << 16) + (packet.Data[offset++] << 24) ; blocks[fields] = "Packets"; } Packet ack = PacketBuilder.BuildPacket("PacketAck", proxyConfig.protocol, blocks, Helpers.MSG_ZEROCODED); ack.Sequence = packet.Sequence; return ack; }
// SendPacket: send a packet from the sim to the client via our fake sim endpoint public void SendPacket(Packet packet, int length, bool skipZero) { if (skipZero || (packet.Data[0] & Helpers.MSG_ZEROCODED) == 0) socket.SendTo(packet.Data, length, SocketFlags.None, clientEndPoint); else { int zeroLength = Helpers.ZeroEncode(packet.Data, length, zeroBuffer); socket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, clientEndPoint); } }
private void ChatIncoming(Packet packet, Simulator simulator) { if (packet.Layout.Name != "ChatFromSimulator") return; string fromname = string.Empty; //Name of source. LLUUID sourceid = new LLUUID(); //UUID of source, object/avatar LLUUID ownerid = new LLUUID(); //UUID of owner, if object UUID = owner of object, if avatar UUID = same as source SLSourceType sourcetype = SLSourceType.None; SLChatType chattype = SLChatType.Whisper; bool audible = false; //Audible: 1 if audible, 0 if beyond 20m (message is null) LLVector3 position = new LLVector3(); //Region local position of source. string message = string.Empty; //Message from source byte command = 0; //Unused? LLUUID commandID = new LLUUID(); //Unused? ArrayList blocks = packet.Blocks(); foreach (Block block in blocks) { foreach (Field field in block.Fields) { switch (field.Layout.Name) { case "SourceID": sourceid = (LLUUID)field.Data; break; case "OwnerID": ownerid = (LLUUID)field.Data; break; case "FromName": fromname = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", string.Empty); break; case "SourceType": sourcetype = (SLSourceType)(byte)field.Data; break; case "ChatType": chattype = (SLChatType)(byte)field.Data; break; case "Audible": audible = ((byte)field.Data == 1 ? true : false); break; case "Message": message = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", string.Empty); break; case "Position": position = (LLVector3)field.Data; break; case "Command": command = (byte)field.Data; break; case "CommandID": commandID = (LLUUID)field.Data; break; } } ChatEventArgs eventArgs = new ChatEventArgs( message, chattype, position, sourcetype, sourceid, ownerid, fromname, audible, command, commandID); if (netcomSync != null) { object[] ea = new object[1]; ea[0] = eventArgs; netcomSync.Invoke(new OnChatRaise(OnChatReceived), ea); } else { OnChatReceived(eventArgs); } } }
// WaitForAck: take care of resending a packet until it's ACKed public void WaitForAck(Packet packet, Direction direction) { Hashtable table = direction == Direction.Incoming ? incomingAcks : outgoingAcks; table.Add(packet.Sequence, packet); }
private void BalanceHandler(Packet packet, Simulator simulator) { if (packet.Layout.Name == "MoneyBalanceReply") { int balance = 0; int squareMetersCredit = 0; string description = ""; LLUUID transactionID = null; bool transactionSuccess = false; foreach (Block block in packet.Blocks()) { foreach (Field field in block.Fields) { if (field.Layout.Name == "MoneyBalance") { balance = (int)field.Data; } else if (field.Layout.Name == "SquareMetersCredit") { squareMetersCredit = (int)field.Data; } else if (field.Layout.Name == "Description") { byte[] byteArray = (byte[])field.Data; description = System.Text.Encoding.ASCII.GetString(byteArray).Replace("\0", ""); } else if (field.Layout.Name == "TransactionID") { transactionID = (LLUUID)field.Data; } else if (field.Layout.Name == "TransactionSuccess") { transactionSuccess = (bool)field.Data; } } } lblBalance.Text = balance.ToString(); } }
// GenericCheck: replace the sim address in a packet with our proxy address private Packet GenericCheck(Packet packet, string block, string fieldIP, string fieldPort, bool active) { Hashtable blocks = PacketUtility.Unbuild(packet); IPEndPoint realSim = new IPEndPoint((IPAddress)PacketUtility.GetField(blocks, block, fieldIP), Convert.ToInt32(PacketUtility.GetField(blocks, block, fieldPort))); IPEndPoint fakeSim = ProxySim(realSim); PacketUtility.SetField(blocks, block, fieldIP, fakeSim.Address); PacketUtility.SetField(blocks, block, fieldPort, (ushort)fakeSim.Port); if (active) activeCircuit = realSim; return PacketBuilder.BuildPacket(packet.Layout.Name, proxyConfig.protocol, blocks, packet.Data[0]); }
// SwapPacket: copy the sequence number and appended ACKs from one packet to another public static void SwapPacket(Packet oldPacket, Packet newPacket, int oldLength) { newPacket.Sequence = oldPacket.Sequence; int oldAcks = (oldPacket.Data[0] & Helpers.MSG_APPENDED_ACKS) == 0 ? 0 : (int)oldPacket.Data[oldLength - 1]; int newAcks = (newPacket.Data[0] & Helpers.MSG_APPENDED_ACKS) == 0 ? 0 : (int)newPacket.Data[newPacket.Data.Length - 1]; if (oldAcks != 0 || newAcks != 0) { int oldAckSize = oldAcks == 0 ? 0 : oldAcks * 4 + 1; int newAckSize = newAcks == 0 ? 0 : newAcks * 4 + 1; byte[] newData = new byte[newPacket.Data.Length - newAckSize + oldAckSize]; Array.Copy(newPacket.Data, 0, newData, 0, newPacket.Data.Length - newAckSize); if (newAcks != 0) newData[0] ^= Helpers.MSG_APPENDED_ACKS; if (oldAcks != 0) { newData[0] |= Helpers.MSG_APPENDED_ACKS; Array.Copy(oldPacket.Data, oldLength - oldAckSize, newData, newPacket.Data.Length - newAckSize, oldAckSize); } newPacket.Data = newData; } }
// LogIncomingMysteryPacket: log an incoming packet we're watching for development purposes private Packet LogIncomingMysteryPacket(Packet packet) { return LogPacket(packet, "incoming mystery"); }
// LogOutgoingMysteryPacket: log an outgoing packet we're watching for development purposes private Packet LogOutgoingMysteryPacket(Packet packet) { return LogPacket(packet, "outgoing mystery"); }
private void InstantMessageIncoming(Packet packet, Simulator simulator) { if (packet.Layout.Name != "ImprovedInstantMessage") return; LLUUID FromAgentID = new LLUUID(); LLUUID ToAgentID = new LLUUID(); uint ParentEstateID = 0; LLUUID RegionID = new LLUUID(); LLVector3 Position = new LLVector3(); bool Offline = false; byte Dialog = 0; LLUUID ID = new LLUUID(); uint Timestamp = 0; DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0); //The Unix epoch! string FromAgentName = string.Empty; string Message = string.Empty; string BinaryBucket = string.Empty; ArrayList blocks = packet.Blocks(); foreach (Block block in blocks) { foreach (Field field in block.Fields) { switch (field.Layout.Name) { case "FromAgentID": FromAgentID = (LLUUID)field.Data; break; case "ToAgentID": ToAgentID = (LLUUID)field.Data; break; case "ParentEstateID": ParentEstateID = (uint)field.Data; break; case "RegionID": RegionID = (LLUUID)field.Data; break; case "Position": Position = (LLVector3)field.Data; break; case "Offline": Offline = ((byte)field.Data == 1 ? true : false); break; case "Dialog": Dialog = (byte)field.Data; break; case "ID": ID = (LLUUID)field.Data; break; case "Timestamp": Timestamp = (uint)field.Data; if (Timestamp == 0) //User is online dt = DateTime.Now; else //User is offline dt = dt.AddSeconds(Timestamp); break; case "FromAgentName": FromAgentName = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", string.Empty); break; case "Message": Message = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", string.Empty); break; case "BinaryBucket": BinaryBucket = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", string.Empty); break; } } InstantMessageEventArgs eventArgs = new InstantMessageEventArgs( FromAgentID, ToAgentID, ParentEstateID, RegionID, Position, Offline, Dialog, ID, dt, FromAgentName, Message, BinaryBucket); if (netcomSync != null) { object[] ea = new object[1]; ea[0] = eventArgs; netcomSync.Invoke(new OnInstantMessageRaise(OnInstantMessageReceived), ea); } else { OnInstantMessageReceived(eventArgs); } } }
// LogPacket: log a packet dump private Packet LogPacket(Packet packet, string type) { Log(type + " packet:", true); Log(packet, true); return PacketBuilder.BuildPacket(packet.Layout.Name, proxyConfig.protocol, PacketUtility.Unbuild(packet), packet.Data[0]); }
private void DirPeopleHandler(Packet packet, Simulator simulator) { lstFindMutex.WaitOne(); foreach (Block block in packet.Blocks()) { if (block.Layout.Name == "QueryReplies") { LLUUID id = null; string firstName = ""; string lastName = ""; bool online = false; foreach (Field field in block.Fields) { if (field.Layout.Name == "AgentID") { id = (LLUUID)field.Data; } else if (field.Layout.Name == "LastName") { lastName = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", ""); } else if (field.Layout.Name == "FirstName") { firstName = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", ""); } else if (field.Layout.Name == "Online") { online = (bool)field.Data; } } if (id != null) { ListViewItem listItem = new ListViewItem(new string[] { firstName + " " + lastName, (online ? "Yes" : "No"), id.ToString() }); lstFind.Items.Add(listItem); } } } lstFindMutex.ReleaseMutex(); }
private void LocationHandler(Packet packet, Simulator simulator) { if (numPositionX.Value == 0) { numPositionX.Value = (decimal)Client.Avatar.Position.X; } if (numPositionY.Value == 0) { numPositionY.Value = (decimal)Client.Avatar.Position.Y; } if (numPositionZ.Value == 0) { numPositionZ.Value = (decimal)Client.Avatar.Position.Z; } }