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.Net;
29 using System.Text;
30 using System.Reflection;
31 using OpenMetaverse;
32 using OpenMetaverse.Packets;
33 using OpenMetaverse.Messages;
34 using OpenMetaverse.StructuredData;
35 using OpenMetaverse.Interfaces;
36 using GridProxy;
37  
38 namespace WinGridProxy
39 {
40 #region Base Class
41 internal abstract class Session
42 {
43 internal const string EmptyXml = "<?xml version=\"1.0\"?><Empty>XML representation of this item is not available.</Empty>";
44 internal const string EmptyString = "String representation of this item is not available.";
45 internal const string EmptyNotation = "Notation representation of this item is not available.";
46  
47 public Direction Direction { get; set; }
48 public String Host { get; set; }
49 public String Protocol { get; set; }
50 public String Name { get; set; }
51 public String ContentType { get; set; }
52 public int Length { get; set; }
53 public DateTime TimeStamp { get; set; }
54  
55 // listview specific stuff, not serialized or deserialized
56 public bool Selected { get; set; }
57 public System.Drawing.Color BackColor { get; set; }
58  
59 public Session()
60 {
61 this.TimeStamp = DateTime.UtcNow;
62 this.Host = this.Protocol = this.Name = String.Empty;
63 this.Length = 0;
64 this.ContentType = String.Empty;
65 }
66  
67 public virtual string ToRawString(Direction direction)
68 {
69 return EmptyString;
70 }
71  
72 public virtual byte[] ToBytes(Direction direction)
73 {
74 return OpenMetaverse.Utils.EmptyBytes;
75 }
76  
77 public virtual string ToXml(Direction direction)
78 {
79 return EmptyXml;
80 }
81  
82 public virtual string ToStringNotation(Direction direction)
83 {
84 return EmptyNotation;
85 }
86  
87 public abstract string ToPrettyString(Direction direction);
88 public abstract byte[] Serialize();
89 public abstract Session Deserialize(byte[] bytes);
90 }
91 #endregion
92  
93 #region Packets
94 internal sealed class SessionPacket : Session
95 {
96 public Packet Packet { get; set; }
97  
98 public SessionPacket() : base() { this.Protocol = "UDP"; }
99 public SessionPacket(Packet packet, Direction direction, IPEndPoint endpoint, String contentType)
100 : base()
101 {
102 this.Packet = packet;
103 this.Name = packet.Type.ToString();
104 this.Direction = direction;
105 this.Host = String.Format("{0}:{1}", endpoint.Address, endpoint.Port);
106 this.ContentType = contentType;
107 this.Length = packet.Length;
108 this.Protocol = "UDP";
109 }
110  
111 public override string ToPrettyString(Direction direction)
112 {
113 if (direction == this.Direction)
114 return PacketDecoder.PacketToString(this.Packet);
115 else
116 return String.Empty;
117 }
118  
119 public override string ToRawString(Direction direction)
120 {
121 if (direction == this.Direction)
122 return PacketDecoder.PacketToString(this.Packet);
123 else
124 return String.Empty;
125 }
126  
127 public override byte[] ToBytes(Direction direction)
128 {
129 if (direction == this.Direction)
130 return Packet.ToBytes();
131 else
132 return base.ToBytes(direction);
133 }
134  
135 //public override string ToXml(Direction direction)
136 //{
137 // if (direction == this.Direction)
138 // return Packet.ToXmlString(this.Packet);
139 // else
140 // return base.ToXml(direction);
141 //}
142  
143 //public override string ToStringNotation(Direction direction)
144 //{
145 // if (direction == this.Direction)
146 // return Packet.GetLLSD(this.Packet).ToString();
147 // else
148 // return base.ToStringNotation(direction);
149 //}
150  
151 public override byte[] Serialize()
152 {
153 OSDMap map = new OSDMap(5);
154 map["Name"] = OSD.FromString(this.Name);
155 map["Host"] = OSD.FromString(this.Host);
156 map["PacketBytes"] = OSD.FromBinary(this.Packet.ToBytes());
157 map["Direction"] = OSD.FromInteger((int)this.Direction);
158 map["ContentType"] = OSD.FromString(this.ContentType);
159  
160 return OpenMetaverse.Utils.StringToBytes(map.ToString());
161 }
162  
163 public override Session Deserialize(byte[] bytes)
164 {
165 OSDMap map = (OSDMap)OSDParser.DeserializeLLSDNotation(OpenMetaverse.Utils.BytesToString(bytes));
166  
167 this.Host = map["Host"].AsString();
168 this.Direction = (Direction)map["Direction"].AsInteger();
169 this.ContentType = map["ContentType"].AsString();
170  
171 byte[] packetData = map["PacketBytes"].AsBinary();
172 this.Length = packetData.Length;
173  
174 int packetEnd = packetData.Length - 1;
175 this.Packet = Packet.BuildPacket(packetData, ref packetEnd, null);
176 this.Name = this.Packet.Type.ToString();
177 return this;
178 }
179 }
180 #endregion Packets
181  
182 #region Capabilities
183 internal sealed class SessionCaps : Session
184 {
185 byte[] RequestBytes { get; set; }
186 byte[] ResponseBytes { get; set; }
187 WebHeaderCollection RequestHeaders { get; set; }
188 WebHeaderCollection ResponseHeaders { get; set; }
189 string FullUri { get; set; }
190  
191 public SessionCaps() : base() { /*this.Protocol = "Caps";*/ }
192 public SessionCaps(byte[] requestBytes, byte[] responseBytes,
193 WebHeaderCollection requestHeaders, WebHeaderCollection responseHeaders,
194 Direction direction, string uri, string capsKey, String proto, string fullUri)
195 : base()
196 {
197 if (requestBytes != null)
198 this.RequestBytes = requestBytes;
199 else
200 this.RequestBytes = OpenMetaverse.Utils.EmptyBytes;
201  
202 if (responseBytes != null)
203 this.ResponseBytes = responseBytes;
204 else
205 this.ResponseBytes = OpenMetaverse.Utils.EmptyBytes;
206 this.RequestHeaders = requestHeaders;
207 this.ResponseHeaders = responseHeaders;
208 this.Protocol = proto;
209 this.FullUri = fullUri;
210  
211 this.Name = capsKey;
212 this.Direction = direction;
213 this.Host = uri;
214 this.ContentType = (direction == Direction.Incoming) ? this.ResponseHeaders.Get("Content-Type") : this.RequestHeaders.Get("Content-Type");
215 this.Length = (requestBytes != null) ? requestBytes.Length : 0;
216 this.Length += (responseBytes != null) ? responseBytes.Length : 0;
217 }
218  
219 public override string ToPrettyString(Direction direction)
220 {
221 try
222 {
223 if (direction == Direction.Incoming)
224 {
225 if (this.ResponseBytes != null && this.ResponseBytes.Length > 0)
226 {
227 IMessage message = null;
228 OSD osd = OSDParser.Deserialize(this.ResponseBytes);
229  
230 if (osd is OSDMap)
231 {
232 OSDMap data = (OSDMap)osd;
233  
234 if (data.ContainsKey("body"))
235 message = OpenMetaverse.Messages.MessageUtils.DecodeEvent(this.Name, (OSDMap)data["body"]);
236 else
237 message = OpenMetaverse.Messages.MessageUtils.DecodeEvent(this.Name, data);
238  
239 if (message != null)
240 return PacketDecoder.MessageToString(message, 0);
241 else
242 return "No Decoder for " + this.Name + Environment.NewLine +
243 OSDParser.SerializeLLSDNotationFormatted(data) + Environment.NewLine +
244 "Please report this at http://jira.openmetaverse.org Be sure to include the entire message.";
245 }
246 }
247 }
248 else
249 {
250 if (this.RequestBytes != null && this.RequestBytes.Length > 0)
251 {
252 if (this.RequestBytes[0] == 60)
253 {
254 OSD osd = OSDParser.Deserialize(this.RequestBytes);
255 if (osd is OSDMap)
256 {
257 IMessage message = null;
258 OSDMap data = (OSDMap)osd;
259  
260 if (data.ContainsKey("body"))
261 message = MessageUtils.DecodeEvent(this.Name, (OSDMap)data["body"]);
262 else
263 message = MessageUtils.DecodeEvent(this.Name, data);
264  
265 if (message != null)
266 return PacketDecoder.MessageToString(message, 0);
267 else
268 return "No Decoder for " + this.Name + Environment.NewLine +
269 OSDParser.SerializeLLSDNotationFormatted(data) + Environment.NewLine +
270 "Please report this at http://jira.openmetaverse.org Be sure to include the entire message.";
271 }
272 else
273 {
274 return osd.ToString();
275 }
276 }
277 else
278 {
279 // this means its probably a script or asset using the uploader capability
280 // so we'll just return the raw bytes as a string
281 //if (this.RequestBytes[0] == 100)
282 //{
283 return Utils.BytesToString(this.RequestBytes);
284 //}
285 }
286 }
287 else
288 {
289 return String.Empty;
290 }
291 }
292 }
293 catch { }
294 return String.Empty;
295 }
296  
297 public override string ToRawString(Direction direction)
298 {
299 try
300 {
301 if (direction == Direction.Incoming)
302 {
303 if (this.ResponseBytes != null)
304 {
305 StringBuilder result = new StringBuilder();
306 foreach (String key in ResponseHeaders.Keys)
307 {
308 result.AppendFormat("{0} {1}" + Environment.NewLine, key, ResponseHeaders[key]);
309 }
310 result.AppendLine();
311 result.AppendLine(OpenMetaverse.Utils.BytesToString(this.ResponseBytes));
312 return result.ToString();
313 }
314 else
315 return String.Empty;
316 }
317 else
318 {
319 if (this.RequestBytes != null)
320 {
321 StringBuilder result = new StringBuilder();
322 result.AppendFormat("Request URI: {0}{1}", FullUri, Environment.NewLine);
323 foreach (String key in RequestHeaders.Keys)
324 {
325 result.AppendFormat("{0}: {1}" + Environment.NewLine, key, RequestHeaders[key]);
326 }
327 result.AppendLine();
328 result.AppendLine(OpenMetaverse.Utils.BytesToString(this.RequestBytes));
329 return result.ToString();
330 }
331 else
332 return String.Empty;
333 }
334 }
335 catch { }
336 return string.Empty;
337 }
338  
339 public override byte[] ToBytes(Direction direction)
340 {
341 if (direction == Direction.Incoming)
342 {
343 if (this.ResponseBytes != null)
344 return this.ResponseBytes;
345 else
346 return base.ToBytes(direction);
347 }
348 else
349 {
350 if (this.RequestBytes != null)
351 return this.RequestBytes;
352 else
353 return base.ToBytes(direction);
354 }
355 }
356  
357 public override string ToStringNotation(Direction direction)
358 {
359 try
360 {
361 if (direction == Direction.Incoming)
362 {
363 if (this.ResponseBytes != null)
364 return BytesToOsd(this.ResponseBytes);
365 //return this.ResponseBytes;
366 else
367 return base.ToStringNotation(direction);
368 }
369 else
370 {
371 if (this.RequestBytes != null)
372 {
373 return BytesToOsd(this.RequestBytes);
374 }
375 else
376 return base.ToStringNotation(direction);
377 }
378 }
379 catch { }
380 return string.Empty;
381 }
382  
383 public override string ToXml(Direction direction)
384 {
385 try
386 {
387 if (direction == Direction.Incoming)
388 {
389 if (this.ResponseBytes != null)
390 return BytesToXml(this.ResponseBytes);
391 else
392 return base.ToXml(direction);
393 }
394 else
395 {
396 if (this.RequestBytes != null)
397 return BytesToXml(this.RequestBytes);
398 else
399 return base.ToXml(direction);
400 }
401 }
402 catch { }
403 return string.Empty;
404 }
405  
406 // Sanity check the bytes are infact OSD
407 private string BytesToOsd(byte[] bytes)
408 {
409 try
410 {
411 OSD osd = OSDParser.Deserialize(bytes);
412 return OSDParser.SerializeLLSDNotationFormatted(osd);
413 }
414 catch (LitJson.JsonException)
415 {
416 // unable to decode as notation format
417 return base.ToStringNotation(this.Direction);
418 }
419 }
420  
421 // Sanity check the bytes are infact an XML
422 private string BytesToXml(byte[] bytes)
423 {
424 String result = Utils.BytesToString(bytes);
425 if (result.StartsWith("<?xml"))
426 return result;
427 else
428 return base.ToXml(this.Direction);
429 }
430  
431  
432 public override byte[] Serialize()
433 {
434 OSDMap map = new OSDMap(5);
435 map["Name"] = OSD.FromString(this.Name);
436 map["Host"] = OSD.FromString(this.Host);
437 map["RequestBytes"] = OSD.FromBinary(this.RequestBytes);
438 map["ResponseBytes"] = OSD.FromBinary(this.ResponseBytes);
439 map["Direction"] = OSD.FromInteger((int)this.Direction);
440 map["ContentType"] = OSD.FromString(this.ContentType);
441 map["Protocol"] = OSD.FromString(this.Protocol);
442  
443 OSDArray requestHeadersArray = new OSDArray();
444 foreach (String key in this.RequestHeaders.Keys)
445 {
446 OSDMap rMap = new OSDMap(1);
447 rMap[key] = OSD.FromString(this.RequestHeaders[key]);
448 requestHeadersArray.Add(rMap);
449 }
450 if(requestHeadersArray.Count > 0)
451 map["RequestHeaders"] = requestHeadersArray;
452  
453 OSDArray responseHeadersArray = new OSDArray();
454 foreach (String key in this.ResponseHeaders.Keys)
455 {
456 OSDMap rMap = new OSDMap(1);
457 rMap[key] = OSD.FromString(this.ResponseHeaders[key]);
458 responseHeadersArray.Add(rMap);
459 }
460 if(responseHeadersArray.Count > 0)
461 map["ResponseHeaders"] = responseHeadersArray;
462  
463 return OpenMetaverse.Utils.StringToBytes(map.ToString());
464 }
465  
466 public override Session Deserialize(byte[] bytes)
467 {
468 OSDMap map = (OSDMap)OSDParser.DeserializeLLSDNotation(OpenMetaverse.Utils.BytesToString(bytes));
469  
470 this.Name = map["Name"].AsString();
471 this.Host = map["Host"].AsString();
472 this.RequestBytes = map["RequestBytes"].AsBinary();
473 this.ResponseBytes = map["ResponseBytes"].AsBinary();
474 this.Direction = (Direction)map["Direction"].AsInteger();
475 this.Length = ResponseBytes.Length + RequestBytes.Length;
476 this.ContentType = map["ContentType"].AsString();
477 this.Protocol = map["Protocol"].AsString();
478  
479 this.RequestHeaders = new WebHeaderCollection();
480 if (map.ContainsKey("RequestHeaders"))
481 {
482 OSDArray requestHeadersArray = (OSDArray)map["RequestHeaders"];
483 for (int i = 0; i < requestHeadersArray.Count; i++)
484 {
485 OSDMap rMap = (OSDMap)requestHeadersArray[i];
486 foreach (string key in rMap.Keys)
487 {
488 this.RequestHeaders.Add(key, rMap[key].AsString());
489 }
490 }
491 }
492  
493 this.ResponseHeaders = new WebHeaderCollection();
494 if (map.ContainsKey("ResponseHeaders"))
495 {
496 OSDArray responseHeadersArray = (OSDArray)map["ResponseHeaders"];
497 for (int i = 0; i < responseHeadersArray.Count; i++)
498 {
499 OSDMap rMap = (OSDMap)responseHeadersArray[i];
500 foreach (string key in rMap.Keys)
501 {
502 this.ResponseHeaders.Add(key, rMap[key].AsString());
503 }
504 }
505 }
506  
507 return this;
508 }
509 }
510 #endregion Capabilities
511  
512 #region Login
513 internal sealed class SessionLogin : Session
514 {
515 private object Data { get; set; }
516 //request, direction, comboBoxLoginURL.Text
517 public SessionLogin() : base() { this.Protocol = "https"; }
518 public SessionLogin(object request, Direction direction, String url, String contentType)
519 : base()
520 {
521 this.Data = request;
522 this.Direction = direction;
523 this.Host = url;
524 this.ContentType = contentType;
525 this.Name = (direction == Direction.Incoming) ? "Login Response" : "Login Request";
526 this.Protocol = "https";
527 this.Length = this.Data.ToString().Length;
528 }
529  
530 public override string ToPrettyString(Direction direction)
531 {
532 if (direction == this.Direction)
533 {
534 return this.Data.ToString();
535 }
536 else
537 {
538 return String.Empty;
539 }
540 }
541  
542 public override string ToRawString(Direction direction)
543 {
544 if (direction == this.Direction)
545 {
546 return this.Data.ToString();
547 }
548 else
549 {
550 return String.Empty;
551 }
552 }
553 public override string ToXml(Direction direction)
554 {
555 return base.ToXml(direction);
556  
557 //if (direction == this.Direction)
558 //{
559 // return this.Data.ToString();
560 //}
561 //else
562 //{
563 // return base.ToXml(direction);
564 //}
565 }
566  
567 public override byte[] ToBytes(Direction direction)
568 {
569 if (direction == this.Direction)
570 {
571 return OpenMetaverse.Utils.StringToBytes(this.Data.ToString());
572 }
573 else
574 {
575 return base.ToBytes(direction);
576 }
577 }
578  
579 public override byte[] Serialize()
580 {
581 OSDMap map = new OSDMap(6);
582 map["Name"] = OSD.FromString(this.Name);
583 map["Host"] = OSD.FromString(this.Host);
584 map["Data"] = OSD.FromString(this.Data.ToString());
585 map["Direction"] = OSD.FromInteger((int)this.Direction);
586 map["ContentType"] = OSD.FromString(this.ContentType);
587 map["Protocol"] = OSD.FromString(this.Protocol);
588  
589 return OpenMetaverse.Utils.StringToBytes(map.ToString());
590 }
591  
592 public override Session Deserialize(byte[] bytes)
593 {
594 OSDMap map = (OSDMap)OSDParser.DeserializeLLSDNotation(OpenMetaverse.Utils.BytesToString(bytes));
595  
596 this.Name = map["Name"].AsString();
597 this.Host = map["Host"].AsString();
598 this.Data = map["Data"].AsString();
599 this.Length = this.Data.ToString().Length;
600 this.Direction = (Direction)map["Direction"].AsInteger();
601 this.ContentType = map["ContentType"].AsString();
602 this.Protocol = map["Protocol"].AsString();
603  
604 return this;
605 }
606 }
607 #endregion Login
608  
609 #region EventQueue Messages
610 internal class SessionEvent : Session
611 {
612 private byte[] ResponseBytes;
613 private WebHeaderCollection ResponseHeaders;
614  
615 public SessionEvent() : base() { this.Protocol = "EventQ"; }
616 public SessionEvent(byte[] responseBytes, WebHeaderCollection responseHeaders,
617 String uri, String capsKey, String proto)
618 : base()
619 {
620 this.Protocol = proto;
621 this.Direction = Direction.Incoming; // EventQueue Messages are always inbound from the simulator
622 this.ResponseBytes = responseBytes;
623 this.ResponseHeaders = responseHeaders;
624 this.Host = uri;
625 this.Name = capsKey;
626 this.ContentType = responseHeaders.Get("Content-Type");
627 var ContentLength = responseHeaders.Get("Content-Length");
628 if (ContentLength != null)
629 this.Length = Int32.Parse (ContentLength);
630 else
631 this.Length = 0;
632 }
633  
634 public override string ToPrettyString(Direction direction)
635 {
636 if (direction == this.Direction)
637 {
638 IMessage message = null;
639 OSD osd = OSDParser.Deserialize(this.ResponseBytes);
640 OSDMap data = (OSDMap)osd;
641 if (data.ContainsKey("body"))
642 message = MessageUtils.DecodeEvent(this.Name, (OSDMap)data["body"]);
643 else
644 message = MessageUtils.DecodeEvent(this.Name, data);
645  
646 if (message != null)
647 return PacketDecoder.MessageToString(message, 0);
648 else
649 return "No Decoder for " + this.Name + Environment.NewLine + osd.ToString();
650 }
651 else
652 {
653 return String.Empty;
654 }
655 }
656  
657 public override byte[] ToBytes(Direction direction)
658 {
659 if (direction == this.Direction)
660 {
661 return this.ResponseBytes;
662 }
663 else
664 {
665 return base.ToBytes(direction);
666 }
667 }
668  
669 public override string ToRawString(Direction direction)
670 {
671  
672 if (direction == this.Direction)
673 {
674 StringBuilder result = new StringBuilder();
675 foreach (String key in ResponseHeaders.Keys)
676 {
677 result.AppendFormat("{0} {1}" + Environment.NewLine, key, ResponseHeaders[key]);
678 }
679 result.AppendLine();
680 result.AppendLine(this.ToXml(direction));
681 return result.ToString();
682 }
683 else
684 {
685 return String.Empty;
686 }
687 }
688  
689 public override string ToXml(Direction direction)
690 {
691 if (direction == this.Direction)
692 {
693 return OpenMetaverse.Utils.BytesToString(this.ResponseBytes);
694 }
695 else
696 {
697 return base.ToXml(direction);
698 }
699 }
700  
701 public override string ToStringNotation(Direction direction)
702 {
703 if (direction == this.Direction)
704 {
705 OSD osd = OSDParser.DeserializeLLSDXml(this.ResponseBytes);
706 return osd.ToString();
707 }
708 else
709 {
710 return base.ToStringNotation(direction);
711 }
712 }
713  
714 public override byte[] Serialize()
715 {
716 OSDMap map = new OSDMap(7);
717 map["Name"] = OSD.FromString(this.Name);
718 map["Host"] = OSD.FromString(this.Host);
719 map["ResponseBytes"] = OSD.FromBinary(this.ResponseBytes);
720 map["Direction"] = OSD.FromInteger((int)this.Direction);
721 map["ContentType"] = OSD.FromString(this.ContentType);
722 map["Protocol"] = OSD.FromString(this.Protocol);
723  
724 OSDArray responseHeadersArray = new OSDArray();
725 foreach (String key in this.ResponseHeaders.Keys)
726 {
727 OSDMap rMap = new OSDMap(1);
728 rMap[key] = OSD.FromString(this.ResponseHeaders[key]);
729 responseHeadersArray.Add(rMap);
730 }
731 map["ResponseHeaders"] = responseHeadersArray;
732  
733 return Utils.StringToBytes(map.ToString());
734 }
735  
736 public override Session Deserialize(byte[] bytes)
737 {
738 OSDMap map = (OSDMap)OSDParser.DeserializeLLSDNotation(OpenMetaverse.Utils.BytesToString(bytes));
739  
740 this.Name = map["Name"].AsString();
741 this.Host = map["Host"].AsString();
742 this.ResponseBytes = map["ResponseBytes"].AsBinary();
743 this.Direction = (Direction)map["Direction"].AsInteger();
744 this.ContentType = map["ContentType"].AsString();
745 this.Protocol = map["Protocol"].AsString();
746 this.Length = ResponseBytes.Length;
747  
748 if (map.ContainsKey("ResponseHeaders"))
749 {
750 this.ResponseHeaders = new WebHeaderCollection();
751 OSDArray responseHeadersArray = (OSDArray)map["ResponseHeaders"];
752 for (int i = 0; i < responseHeadersArray.Count; i++)
753 {
754 OSDMap rMap = (OSDMap)responseHeadersArray[i];
755 foreach (string key in rMap.Keys)
756 {
757 this.ResponseHeaders.Add(key, rMap[key].AsString());
758 }
759 }
760 }
761 return this;
762 }
763 }
764 #endregion
765 }