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 openmetaverse.org 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.Collections;
29 using System.Collections.Generic;
30 using System.Reflection;
31 using OpenMetaverse.StructuredData;
32  
33 namespace OpenMetaverse.Packets
34 {
35 public abstract partial class Packet
36 {
37 #region Serialization/Deserialization
38  
39 public static string ToXmlString(Packet packet)
40 {
41 return OSDParser.SerializeLLSDXmlString(GetLLSD(packet));
42 }
43  
44 public static OSD GetLLSD(Packet packet)
45 {
46 OSDMap body = new OSDMap();
47 Type type = packet.GetType();
48  
49 foreach (FieldInfo field in type.GetFields())
50 {
51 if (field.IsPublic)
52 {
53 Type blockType = field.FieldType;
54  
55 if (blockType.IsArray)
56 {
57 object blockArray = field.GetValue(packet);
58 Array array = (Array)blockArray;
59 OSDArray blockList = new OSDArray(array.Length);
60 IEnumerator ie = array.GetEnumerator();
61  
62 while (ie.MoveNext())
63 {
64 object block = ie.Current;
65 blockList.Add(BuildLLSDBlock(block));
66 }
67  
68 body[field.Name] = blockList;
69 }
70 else
71 {
72 object block = field.GetValue(packet);
73 body[field.Name] = BuildLLSDBlock(block);
74 }
75 }
76 }
77  
78 return body;
79 }
80  
81 public static byte[] ToBinary(Packet packet)
82 {
83 return OSDParser.SerializeLLSDBinary(GetLLSD(packet));
84 }
85  
86 public static Packet FromXmlString(string xml)
87 {
88 System.Xml.XmlTextReader reader =
89 new System.Xml.XmlTextReader(new System.IO.MemoryStream(Utils.StringToBytes(xml)));
90  
91 return FromLLSD(OSDParser.DeserializeLLSDXml(reader));
92 }
93  
94 public static Packet FromLLSD(OSD osd)
95 {
96 // FIXME: Need the inverse of the reflection magic above done here
97 throw new NotImplementedException();
98 }
99  
100 #endregion Serialization/Deserialization
101  
102 /// <summary>
103 /// Attempts to convert an LLSD structure to a known Packet type
104 /// </summary>
105 /// <param name="capsEventName">Event name, this must match an actual
106 /// packet name for a Packet to be successfully built</param>
107 /// <param name="body">LLSD to convert to a Packet</param>
108 /// <returns>A Packet on success, otherwise null</returns>
109 public static Packet BuildPacket(string capsEventName, OSDMap body)
110 {
111 Assembly assembly = Assembly.GetExecutingAssembly();
112  
113 // Check if we have a subclass of packet with the same name as this event
114 Type type = assembly.GetType("OpenMetaverse.Packets." + capsEventName + "Packet", false);
115 if (type == null)
116 return null;
117  
118 Packet packet = null;
119  
120 try
121 {
122 // Create an instance of the object
123 packet = (Packet)Activator.CreateInstance(type);
124  
125 // Iterate over all of the fields in the packet class, looking for matches in the LLSD
126 foreach (FieldInfo field in type.GetFields())
127 {
128 if (body.ContainsKey(field.Name))
129 {
130 Type blockType = field.FieldType;
131  
132 if (blockType.IsArray)
133 {
134 OSDArray array = (OSDArray)body[field.Name];
135 Type elementType = blockType.GetElementType();
136 object[] blockArray = (object[])Array.CreateInstance(elementType, array.Count);
137  
138 for (int i = 0; i < array.Count; i++)
139 {
140 OSDMap map = (OSDMap)array[i];
141 blockArray[i] = ParseLLSDBlock(map, elementType);
142 }
143  
144 field.SetValue(packet, blockArray);
145 }
146 else
147 {
148 OSDMap map = (OSDMap)((OSDArray)body[field.Name])[0];
149 field.SetValue(packet, ParseLLSDBlock(map, blockType));
150 }
151 }
152 }
153 }
154 catch (Exception)
155 {
156 //FIXME Logger.Log(e.Message, Helpers.LogLevel.Error, e);
157 }
158  
159 return packet;
160 }
161  
162 private static object ParseLLSDBlock(OSDMap blockData, Type blockType)
163 {
164 object block = Activator.CreateInstance(blockType);
165  
166 // Iterate over each field and set the value if a match was found in the LLSD
167 foreach (FieldInfo field in blockType.GetFields())
168 {
169 if (blockData.ContainsKey(field.Name))
170 {
171 Type fieldType = field.FieldType;
172  
173 if (fieldType == typeof(ulong))
174 {
175 // ulongs come in as a byte array, convert it manually here
176 byte[] bytes = blockData[field.Name].AsBinary();
177 ulong value = Utils.BytesToUInt64(bytes);
178 field.SetValue(block, value);
179 }
180 else if (fieldType == typeof(uint))
181 {
182 // uints come in as a byte array, convert it manually here
183 byte[] bytes = blockData[field.Name].AsBinary();
184 uint value = Utils.BytesToUInt(bytes);
185 field.SetValue(block, value);
186 }
187 else if (fieldType == typeof(ushort))
188 {
189 // Just need a bit of manual typecasting love here
190 field.SetValue(block, (ushort)blockData[field.Name].AsInteger());
191 }
192 else if (fieldType == typeof(byte))
193 {
194 // Just need a bit of manual typecasting love here
195 field.SetValue(block, (byte)blockData[field.Name].AsInteger());
196 }
197 else if (fieldType == typeof(sbyte))
198 {
199 field.SetValue(block, (sbyte)blockData[field.Name].AsInteger());
200 }
201 else if (fieldType == typeof(short))
202 {
203 field.SetValue(block, (short)blockData[field.Name].AsInteger());
204 }
205 else if (fieldType == typeof(string))
206 {
207 field.SetValue(block, blockData[field.Name].AsString());
208 }
209 else if (fieldType == typeof(bool))
210 {
211 field.SetValue(block, blockData[field.Name].AsBoolean());
212 }
213 else if (fieldType == typeof(float))
214 {
215 field.SetValue(block, (float)blockData[field.Name].AsReal());
216 }
217 else if (fieldType == typeof(double))
218 {
219 field.SetValue(block, blockData[field.Name].AsReal());
220 }
221 else if (fieldType == typeof(int))
222 {
223 field.SetValue(block, blockData[field.Name].AsInteger());
224 }
225 else if (fieldType == typeof(UUID))
226 {
227 field.SetValue(block, blockData[field.Name].AsUUID());
228 }
229 else if (fieldType == typeof(Vector3))
230 {
231 Vector3 vec = ((OSDArray)blockData[field.Name]).AsVector3();
232 field.SetValue(block, vec);
233 }
234 else if (fieldType == typeof(Vector4))
235 {
236 Vector4 vec = ((OSDArray)blockData[field.Name]).AsVector4();
237 field.SetValue(block, vec);
238 }
239 else if (fieldType == typeof(Quaternion))
240 {
241 Quaternion quat = ((OSDArray)blockData[field.Name]).AsQuaternion();
242 field.SetValue(block, quat);
243 }
244 else if (fieldType == typeof(byte[]) && blockData[field.Name].Type == OSDType.String)
245 {
246 field.SetValue(block, Utils.StringToBytes(blockData[field.Name]));
247 }
248 }
249 }
250  
251 // Additional fields come as properties, Handle those as well.
252 foreach (PropertyInfo property in blockType.GetProperties())
253 {
254 if (blockData.ContainsKey(property.Name))
255 {
256 OSDType proptype = blockData[property.Name].Type;
257 MethodInfo set = property.GetSetMethod();
258  
259 if (proptype.Equals(OSDType.Binary))
260 {
261 set.Invoke(block, new object[] { blockData[property.Name].AsBinary() });
262 }
263 else
264 set.Invoke(block, new object[] { Utils.StringToBytes(blockData[property.Name].AsString()) });
265 }
266 }
267  
268 return block;
269 }
270  
271 private static OSD BuildLLSDBlock(object block)
272 {
273 OSDMap map = new OSDMap();
274 Type blockType = block.GetType();
275  
276 foreach (FieldInfo field in blockType.GetFields())
277 {
278 if (field.IsPublic)
279 map[field.Name] = OSD.FromObject(field.GetValue(block));
280 }
281  
282 foreach (PropertyInfo property in blockType.GetProperties())
283 {
284 if (property.Name != "Length")
285 {
286 map[property.Name] = OSD.FromObject(property.GetValue(block, null));
287 }
288 }
289  
290 return map;
291 }
292 }
293 }