123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- namespace UdPunching
- {
- public class ExchangeMessage
- {
- // [0....] Flags
- // [1....] Section count
- // [2....] Section Type
- // [3...N] Section Content
- // [N+1..] Next Section Type
- public ExchangeMessageFlags Flags { get; set; }
- public DateTime? PeerTimeStamp { get; set; }
- public IPEndPoint PeerEndPoint { get; set; }
- public Guid? PeerId { get; set; }
- //TODO: more properties
- public ExchangeMessage()
- {
- }
- public ExchangeMessage(byte[] data)
- {
- var ptr = -1;
- Flags = (ExchangeMessageFlags)data[++ptr];
- var count = data[++ptr];
- for (var i = 0; i < count; i++)
- {
- var section = (ExchangeMessageSection)data[++ptr];
- switch (section)
- {
- case ExchangeMessageSection.TimeStamp:
- ptr += data.ReadUnixTimeStamp(++ptr, out var timeStamp);
- PeerTimeStamp = timeStamp;
- break;
- case ExchangeMessageSection.PeerEndPoint:
- ptr += data.ReadIpEndPoint(++ptr, out var ipEndPoint);
- PeerEndPoint = ipEndPoint;
- break;
- case ExchangeMessageSection.PeerId:
- PeerId = new Guid(data.Skip(++ptr).Take(16).ToArray());
- ptr += 16;
- break;
- default:
- //TODO: handle more sections
- throw new ArgumentOutOfRangeException();
- }
- }
- }
- private Dictionary<ExchangeMessageSection, byte[]> CreateSectionDictionary()
- {
- var dic = new Dictionary<ExchangeMessageSection, byte[]>();
- if (PeerTimeStamp.HasValue)
- {
- dic[ExchangeMessageSection.TimeStamp] = PeerTimeStamp.Value.ToUnixTimeStamp().ToLeBytes();
- }
- if (null != PeerEndPoint)
- {
- var buf = new byte[17];
- PeerEndPoint.Address.ToPaddingString().ToAsciiBytes(buf);
- PeerEndPoint.Port.ToLe16Bytes(buf, 15);
- dic[ExchangeMessageSection.PeerEndPoint] = buf;
- }
- if (PeerId.HasValue)
- {
- dic[ExchangeMessageSection.PeerId] = PeerId.Value.ToByteArray();
- }
- //TODO: add more sections from properties
- return dic;
- }
- public byte[] ToBytes()
- {
- var dic = CreateSectionDictionary();
- var lst = new List<byte>(1 + 1 + dic.Count + dic.Sum(p => p.Value.Length))
- {
- (byte)Flags,
- (byte)dic.Count
- };
- foreach (var kvp in dic)
- {
- lst.Add((byte)kvp.Key);
- lst.AddRange(kvp.Value);
- }
- return lst.ToArray();
- }
- public void WriteToBuffer(byte[] buffer)
- {
- var dic = CreateSectionDictionary();
- var ptr = -1;
- buffer[++ptr] = (byte)Flags;
- buffer[++ptr] = (byte)dic.Count;
- foreach (var item in dic)
- {
- buffer[++ptr] = (byte)item.Key;
- item.Value.CopyTo(buffer, ++ptr);
- }
- }
- }
- }
|