corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) 2006-2014, openmetaverse.org
3 * All rights reserved.
4 *
5 * - Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * - Neither the name of the Second Life Reverse Engineering Team nor the names
11 * of its contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26  
27 using System;
28 using System.Text;
29 using OpenMetaverse;
30  
31 namespace OpenMetaverse
32 {
33 /// <summary>
34 ///
35 /// </summary>
36 public enum PacketFrequency : byte
37 {
38 /// <summary></summary>
39 Low,
40 /// <summary></summary>
41 Medium,
42 /// <summary></summary>
43 High
44 }
45 }
46  
47 namespace OpenMetaverse.Packets
48 {
49 /// <summary>
50 /// Thrown when a packet could not be successfully deserialized
51 /// </summary>
52 public class MalformedDataException : ApplicationException
53 {
54 /// <summary>
55 /// Default constructor
56 /// </summary>
57 public MalformedDataException() { }
58  
59 /// <summary>
60 /// Constructor that takes an additional error message
61 /// </summary>
62 /// <param name="Message">An error message to attach to this exception</param>
63 public MalformedDataException(string Message)
64 : base(Message)
65 {
66 this.Source = "Packet decoding";
67 }
68 }
69  
70 /// <summary>
71 /// The header of a message template packet. Holds packet flags, sequence
72 /// number, packet ID, and any ACKs that will be appended at the end of
73 /// the packet
74 /// </summary>
75 public struct Header
76 {
77 public bool Reliable;
78 public bool Resent;
79 public bool Zerocoded;
80 public bool AppendedAcks;
81 public uint Sequence;
82 public ushort ID;
83 public PacketFrequency Frequency;
84 public uint[] AckList;
85  
86 public void ToBytes(byte[] bytes, ref int i)
87 {
88 byte flags = 0;
89 if (Reliable) flags |= Helpers.MSG_RELIABLE;
90 if (Resent) flags |= Helpers.MSG_RESENT;
91 if (Zerocoded) flags |= Helpers.MSG_ZEROCODED;
92 if (AppendedAcks) flags |= Helpers.MSG_APPENDED_ACKS;
93  
94 // Flags
95 bytes[i++] = flags;
96  
97 // Sequence number
98 Utils.UIntToBytesBig(Sequence, bytes, i);
99 i += 4;
100  
101 // Extra byte
102 bytes[i++] = 0;
103  
104 // Packet ID
105 switch (Frequency)
106 {
107 case PacketFrequency.High:
108 // 1 byte ID
109 bytes[i++] = (byte)ID;
110 break;
111 case PacketFrequency.Medium:
112 // 2 byte ID
113 bytes[i++] = 0xFF;
114 bytes[i++] = (byte)ID;
115 break;
116 case PacketFrequency.Low:
117 // 4 byte ID
118 bytes[i++] = 0xFF;
119 bytes[i++] = 0xFF;
120 Utils.UInt16ToBytesBig(ID, bytes, i);
121 i += 2;
122 break;
123 }
124 }
125  
126 public void FromBytes(byte[] bytes, ref int pos, ref int packetEnd)
127 {
128 this = BuildHeader(bytes, ref pos, ref packetEnd);
129 }
130  
131 /// <summary>
132 /// Convert the AckList to a byte array, used for packet serializing
133 /// </summary>
134 /// <param name="bytes">Reference to the target byte array</param>
135 /// <param name="i">Beginning position to start writing to in the byte
136 /// array, will be updated with the ending position of the ACK list</param>
137 public void AcksToBytes(byte[] bytes, ref int i)
138 {
139 foreach (uint ack in AckList)
140 {
141 Utils.UIntToBytesBig(ack, bytes, i);
142 i += 4;
143 }
144 if (AckList.Length > 0) { bytes[i++] = (byte)AckList.Length; }
145 }
146  
147 /// <summary>
148 ///
149 /// </summary>
150 /// <param name="bytes"></param>
151 /// <param name="pos"></param>
152 /// <param name="packetEnd"></param>
153 /// <returns></returns>
154 public static Header BuildHeader(byte[] bytes, ref int pos, ref int packetEnd)
155 {
156 Header header;
157 byte flags = bytes[pos];
158  
159 header.AppendedAcks = (flags & Helpers.MSG_APPENDED_ACKS) != 0;
160 header.Reliable = (flags & Helpers.MSG_RELIABLE) != 0;
161 header.Resent = (flags & Helpers.MSG_RESENT) != 0;
162 header.Zerocoded = (flags & Helpers.MSG_ZEROCODED) != 0;
163 header.Sequence = (uint)((bytes[pos + 1] << 24) + (bytes[pos + 2] << 16) + (bytes[pos + 3] << 8) + bytes[pos + 4]);
164  
165 // Set the frequency and packet ID number
166 if (bytes[pos + 6] == 0xFF)
167 {
168 if (bytes[pos + 7] == 0xFF)
169 {
170 header.Frequency = PacketFrequency.Low;
171 if (header.Zerocoded && bytes[pos + 8] == 0)
172 header.ID = bytes[pos + 10];
173 else
174 header.ID = (ushort)((bytes[pos + 8] << 8) + bytes[pos + 9]);
175  
176 pos += 10;
177 }
178 else
179 {
180 header.Frequency = PacketFrequency.Medium;
181 header.ID = bytes[pos + 7];
182  
183 pos += 8;
184 }
185 }
186 else
187 {
188 header.Frequency = PacketFrequency.High;
189 header.ID = bytes[pos + 6];
190  
191 pos += 7;
192 }
193  
194 header.AckList = null;
195 CreateAckList(ref header, bytes, ref packetEnd);
196  
197 return header;
198 }
199  
200 /// <summary>
201 ///
202 /// </summary>
203 /// <param name="header"></param>
204 /// <param name="bytes"></param>
205 /// <param name="packetEnd"></param>
206 static void CreateAckList(ref Header header, byte[] bytes, ref int packetEnd)
207 {
208 if (header.AppendedAcks)
209 {
210 int count = bytes[packetEnd--];
211 header.AckList = new uint[count];
212  
213 for (int i = 0; i < count; i++)
214 {
215 header.AckList[i] = (uint)(
216 (bytes[(packetEnd - i * 4) - 3] << 24) |
217 (bytes[(packetEnd - i * 4) - 2] << 16) |
218 (bytes[(packetEnd - i * 4) - 1] << 8) |
219 (bytes[(packetEnd - i * 4) ]));
220 }
221  
222 packetEnd -= (count * 4);
223 }
224 }
225 }
226  
227 /// <summary>
228 /// A block of data in a packet. Packets are composed of one or more blocks,
229 /// each block containing one or more fields
230 /// </summary>
231 public abstract class PacketBlock
232 {
233 /// <summary>Current length of the data in this packet</summary>
234 public abstract int Length { get; }
235  
236 /// <summary>
237 /// Create a block from a byte array
238 /// </summary>
239 /// <param name="bytes">Byte array containing the serialized block</param>
240 /// <param name="i">Starting position of the block in the byte array.
241 /// This will point to the data after the end of the block when the
242 /// call returns</param>
243 public abstract void FromBytes(byte[] bytes, ref int i);
244  
245 /// <summary>
246 /// Serialize this block into a byte array
247 /// </summary>
248 /// <param name="bytes">Byte array to serialize this block into</param>
249 /// <param name="i">Starting position in the byte array to serialize to.
250 /// This will point to the position directly after the end of the
251 /// serialized block when the call returns</param>
252 public abstract void ToBytes(byte[] bytes, ref int i);
253 }