- refactored the server

- corrected an issue submitted by Ian McCarty
master
neonp_cp 2009-10-21 09:03:46 -07:00
parent def44384aa
commit 190b8f904b
67 changed files with 2339 additions and 231 deletions

View File

@ -13,8 +13,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Network.UPnP.Services", "UP
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UPnPReader", "UPnPReader\UPnPReader.csproj", "{5E066080-8EC9-47B8-A1D3-171D06829484}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Network.Rest", "Rest\Network.Rest.csproj", "{3FFE9D8C-3914-4DD1-BB7C-8D4359216806}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Network.UPnP.DLNA", "DLNA\Network.UPnP.DLNA.csproj", "{8BF16D75-B05B-48AF-A72D-5CDDC861DFD6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MEF.Bonjour", "MEF.Bonjour\MEF.Bonjour.csproj", "{94D114DE-DA48-4060-9B7A-3059BF75E87D}"
@ -25,7 +23,66 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Network.Rest.MEF", "Network
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Network.Bonjour.Services", "Network.Bonjour.Services\Network.Bonjour.Services.csproj", "{8CC2B14D-E24B-41A8-AB93-17F130905E29}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Network", "Network", "{94021DC9-3285-44A8-B830-64489127EE2D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Network", "Network\Network.csproj", "{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Network.Rest", "Network.Rest\Network.Rest.csproj", "{13A68F9C-F095-409E-A97D-A05FFCDCE210}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Network.Tests", "Network.Tests\Network.Tests.csproj", "{61DB9D8D-F2EA-40DC-8F37-58092891A6A5}"
EndProject
Global
GlobalSection(TeamFoundationVersionControl) = preSolution
SccNumberOfProjects = 15
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
SccTeamFoundationServer = https://tfs09.codeplex.com/
SccLocalPath0 = .
SccProjectUniqueName1 = SD\\Network.ZeroConf.csproj
SccProjectName1 = SD
SccLocalPath1 = SD
SccProjectUniqueName2 = Bonjour.NET\\Network.Bonjour.csproj
SccProjectName2 = Bonjour.NET
SccLocalPath2 = Bonjour.NET
SccProjectUniqueName3 = mDNSReader\\mDNSReader.csproj
SccProjectName3 = mDNSReader
SccLocalPath3 = mDNSReader
SccProjectUniqueName4 = DnsResolver\\Network.Dns.csproj
SccProjectName4 = DnsResolver
SccLocalPath4 = DnsResolver
SccProjectUniqueName5 = UPnP\\Network.UPnP.Services.csproj
SccProjectName5 = UPnP
SccLocalPath5 = UPnP
SccProjectUniqueName6 = UPnPReader\\UPnPReader.csproj
SccProjectName6 = UPnPReader
SccLocalPath6 = UPnPReader
SccProjectUniqueName7 = DLNA\\Network.UPnP.DLNA.csproj
SccProjectName7 = DLNA
SccLocalPath7 = DLNA
SccProjectUniqueName8 = MEF.Bonjour\\MEF.Bonjour.csproj
SccProjectName8 = MEF.Bonjour
SccLocalPath8 = MEF.Bonjour
SccProjectUniqueName9 = MEF.Bonjour.Tests\\MEF.Bonjour.Tests.csproj
SccProjectName9 = MEF.Bonjour.Tests
SccLocalPath9 = MEF.Bonjour.Tests
SccProjectUniqueName10 = Network.Rest.MEF\\Network.Rest.MEF.csproj
SccProjectName10 = Network.Rest.MEF
SccLocalPath10 = Network.Rest.MEF
SccProjectUniqueName11 = Network.Bonjour.Services\\Network.Bonjour.Services.csproj
SccProjectName11 = Network.Bonjour.Services
SccLocalPath11 = Network.Bonjour.Services
SccProjectUniqueName12 = Network\\Network.csproj
SccProjectTopLevelParentUniqueName12 = Bonjour.NET.sln
SccProjectName12 = Network
SccLocalPath12 = Network
SccProjectUniqueName13 = Network.Rest\\Network.Rest.csproj
SccProjectTopLevelParentUniqueName13 = Bonjour.NET.sln
SccProjectName13 = Network.Rest
SccLocalPath13 = Network.Rest
SccProjectUniqueName14 = Network.Tests\\Network.Tests.csproj
SccProjectTopLevelParentUniqueName14 = Bonjour.NET.sln
SccProjectName14 = Network.Tests
SccLocalPath14 = Network.Tests
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
@ -55,10 +112,6 @@ Global
{5E066080-8EC9-47B8-A1D3-171D06829484}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E066080-8EC9-47B8-A1D3-171D06829484}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E066080-8EC9-47B8-A1D3-171D06829484}.Release|Any CPU.Build.0 = Release|Any CPU
{3FFE9D8C-3914-4DD1-BB7C-8D4359216806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3FFE9D8C-3914-4DD1-BB7C-8D4359216806}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3FFE9D8C-3914-4DD1-BB7C-8D4359216806}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3FFE9D8C-3914-4DD1-BB7C-8D4359216806}.Release|Any CPU.Build.0 = Release|Any CPU
{8BF16D75-B05B-48AF-A72D-5CDDC861DFD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8BF16D75-B05B-48AF-A72D-5CDDC861DFD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8BF16D75-B05B-48AF-A72D-5CDDC861DFD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -79,8 +132,25 @@ Global
{8CC2B14D-E24B-41A8-AB93-17F130905E29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CC2B14D-E24B-41A8-AB93-17F130905E29}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CC2B14D-E24B-41A8-AB93-17F130905E29}.Release|Any CPU.Build.0 = Release|Any CPU
{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}.Release|Any CPU.Build.0 = Release|Any CPU
{13A68F9C-F095-409E-A97D-A05FFCDCE210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{13A68F9C-F095-409E-A97D-A05FFCDCE210}.Debug|Any CPU.Build.0 = Debug|Any CPU
{13A68F9C-F095-409E-A97D-A05FFCDCE210}.Release|Any CPU.ActiveCfg = Release|Any CPU
{13A68F9C-F095-409E-A97D-A05FFCDCE210}.Release|Any CPU.Build.0 = Release|Any CPU
{61DB9D8D-F2EA-40DC-8F37-58092891A6A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61DB9D8D-F2EA-40DC-8F37-58092891A6A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61DB9D8D-F2EA-40DC-8F37-58092891A6A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61DB9D8D-F2EA-40DC-8F37-58092891A6A5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F} = {94021DC9-3285-44A8-B830-64489127EE2D}
{13A68F9C-F095-409E-A97D-A05FFCDCE210} = {94021DC9-3285-44A8-B830-64489127EE2D}
{61DB9D8D-F2EA-40DC-8F37-58092891A6A5} = {94021DC9-3285-44A8-B830-64489127EE2D}
EndGlobalSection
EndGlobal

10
Bonjour.NET.vssscc Normal file
View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
}

View File

@ -42,8 +42,8 @@ namespace Network.Bonjour
EnhanceService(a);
}
MDnsClient resolver;
MDnsClient publisher;
MDnsServer resolver;
MDnsServer publisher;
AutoResetEvent resolved = new AutoResetEvent(false);
bool needsToBeResolvedLater = false;
@ -58,9 +58,9 @@ namespace Network.Bonjour
return;
}
needsToBeResolvedLater = false;
resolver = MDnsClient.CreateAndResolve(HostName);
resolver = new MDnsServer().Resolve(HostName);
resolver.AnswerReceived += client_AnswerReceived;
resolver.Start();
resolver.StartUdp();
resolved.WaitOne();
}
@ -176,26 +176,10 @@ namespace Network.Bonjour
public void Publish()
{
publisher = new MDnsClient(new IPEndPoint(IPAddress.Any, 5353));
publisher.QueryReceived += new ObjectEvent<Message>(publisher_QueryReceived);
publisher.Start();
Message m = new Message();
m.From = MDnsClient.EndPoint;
m.QueryResponse = Qr.Answer;
m.OpCode = OpCode.Query;
m.AuthoritativeAnswer = true;
m.ID = 0;
m.ResponseCode = ResponseCode.NoError;
foreach (Network.Dns.EndPoint ep in Addresses)
{
foreach (var address in ep.Addresses)
m.Additionals.Add(new Answer() { Class = Class.IN, DomainName = HostName, Ttl = 500, Type = address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork ? Network.Dns.Type.A : Network.Dns.Type.AAAA, ResponseData = new HostAddress() { Address = address } });
m.Additionals.Add(new Answer() { Class = Class.IN, DomainName = Name + "." + Protocol, Ttl = 500, Type = Network.Dns.Type.SRV, ResponseData = new Srv() { Port = ep.Port, Target = ep.DomainName } });
m.Additionals.Add(new Answer() { Class = Class.IN, DomainName = Name + "." + Protocol, Ttl = 500, Type = Network.Dns.Type.TXT, ResponseData = new Txt() { Properties = properties } });
m.Authorities.Add(new Answer() { Class = Class.IN, DomainName = Protocol, Ttl = 500, Type = Network.Dns.Type.PTR, ResponseData = new Ptr() { DomainName = Name + "." + Protocol } });
}
publisher.Send(m, m.From);
publisher = new MDnsServer(new IPEndPoint(IPAddress.Any, 5353));
publisher.QueryReceived += publisher_QueryReceived;
publisher.StartUdp();
Renew(500);
}
void publisher_QueryReceived(Message item)
@ -216,7 +200,7 @@ namespace Network.Bonjour
item.Answers.Add(new Answer() { Class = Class.IN, DomainName = Protocol, Ttl = 5, Type = Network.Dns.Type.TXT, ResponseData = new Txt() { Properties = properties } });
}
publisher.Send(item, item.From);
//publisher.Send(item, item.From);
}
}
}
@ -297,6 +281,23 @@ namespace Network.Bonjour
public void Renew(uint ttl)
{
expiration = DateTime.Now.AddSeconds(ttl);
Message m = new Message();
m.From = MDnsServer.EndPoint;
m.QueryResponse = Qr.Answer;
m.OpCode = OpCode.Query;
m.AuthoritativeAnswer = true;
m.ID = 0;
m.ResponseCode = ResponseCode.NoError;
foreach (Network.Dns.EndPoint ep in Addresses)
{
foreach (var address in ep.Addresses)
m.Additionals.Add(new Answer() { Class = Class.IN, DomainName = HostName, Ttl = ttl, Type = address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork ? Network.Dns.Type.A : Network.Dns.Type.AAAA, ResponseData = new HostAddress() { Address = address } });
m.Additionals.Add(new Answer() { Class = Class.IN, DomainName = Name + "." + Protocol, Ttl = ttl, Type = Network.Dns.Type.SRV, ResponseData = new Srv() { Port = ep.Port, Target = ep.DomainName } });
m.Additionals.Add(new Answer() { Class = Class.IN, DomainName = Name + "." + Protocol, Ttl = ttl, Type = Network.Dns.Type.TXT, ResponseData = new Txt() { Properties = properties } });
m.Authorities.Add(new Answer() { Class = Class.IN, DomainName = Protocol, Ttl = ttl, Type = Network.Dns.Type.PTR, ResponseData = new Ptr() { DomainName = Name + "." + Protocol } });
}
publisher.Send(m, m.From);
}
#region IService Members
@ -315,6 +316,7 @@ namespace Network.Bonjour
else
AddAddress(endpoint);
}
State = State.Updated;
}
}

View File

@ -14,7 +14,7 @@ namespace Network.Bonjour
public class BonjourServiceResolver : IServiceResolver, IDisposable
{
MDnsClient client;
MDnsServer client;
IList<IService> services;
private StringCollection protocols;
@ -46,13 +46,12 @@ namespace Network.Bonjour
protocols.Add(protocol);
if (client == null)
{
client = MDnsClient.CreateAndResolve(protocol);
client = new MDnsServer();
client.AnswerReceived += client_AnswerReceived;
client.Resolve(protocol);
}
else
client.Resolve(protocol);
if (!client.IsStarted)
client.Start();
}
public IList<IService> Resolve(string protocol, TimeSpan timeout, int minCountServices, int maxCountServices)
@ -93,6 +92,7 @@ namespace Network.Bonjour
rightService.Merge(service);
break;
case State.Removed:
((Service)rightService).State = State.Removed;
services.Remove(rightService);
if (ServiceRemoved != null)
ServiceRemoved(rightService);
@ -109,6 +109,16 @@ namespace Network.Bonjour
else
AddService(service);
}
foreach (var service in services)
{
if (service.State == State.Updated)
{
if (ServiceFound != null)
ServiceFound(service);
((Service)service).State = State.UpToDate;
}
}
}
private void AddService(IService service)
@ -116,9 +126,6 @@ namespace Network.Bonjour
if (!protocols.Contains(service.Protocol))
return;
this.services.Add(service);
if (ServiceFound != null)
ServiceFound(service);
((Service)service).State = State.UpToDate;
}
#endregion

88
Bonjour.NET/MDnsServer.cs Normal file
View File

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Network.Dns;
using System.Net;
using Network.ZeroConf;
namespace Network.Bonjour
{
public class MDnsServer : DnsServer
{
public static readonly IPEndPoint EndPoint = new IPEndPoint(IPAddress.Parse("224.0.0.251"), 5353);
public MDnsServer(ushort port)
: base(port)
{
}
public MDnsServer(IPAddress address, ushort port)
: base(address, port)
{
}
public MDnsServer(IPEndPoint host)
: base(host)
{
}
public MDnsServer()
: this(EndPoint)
{
this.Started += new EventHandler(MDnsServer_Started);
}
void MDnsServer_Started(object sender, EventArgs e)
{
if (this.IsUdp)
udp.MulticastLoopback = true;
}
public event ObjectEvent<Message> AnswerReceived;
public event ObjectEvent<Message> QueryReceived;
ushort requestId;
public MDnsServer Resolve(string dname)
{
Message message = new Message();
List<byte> guid = Guid.NewGuid().ToByteArray().Take(2).ToList();
requestId = (ushort)(guid[0] * byte.MaxValue + guid[1]);
message.ID = requestId;
message.Questions.Add(new Question(dname));
if (!IsStarted)
StartUdp();
Send(message, EndPoint);
return this;
}
protected override void OnRequestReceived(RequestEventArgs<Message, Message> rea)
{
base.OnRequestReceived(rea);
if ((rea.Request.ID == requestId && rea.Request.QueryResponse == Qr.Answer) || rea.Request.ID == 0)
{
if (AnswerReceived != null)
AnswerReceived(rea.Request.Clone());
}
if ((rea.Request.ID != requestId || rea.Request.ID == 0) && rea.Request.QueryResponse == Qr.Query)
{
this.requestId = 0;
Message response = rea.Request.Clone();
if (QueryReceived != null)
QueryReceived(response);
if (response.AnswerEntries > 0)
rea.Response = response;
}
}
internal new void Send(Message response, IPEndPoint remote)
{
base.Send(response, remote);
}
}
}

View File

@ -12,6 +12,10 @@
<AssemblyName>Bonjour.NET</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -47,7 +51,7 @@
<ItemGroup>
<Compile Include="BonjourService.cs" />
<Compile Include="BonjourServiceResolver.cs" />
<Compile Include="MDnsClient.cs" />
<Compile Include="MDnsServer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
@ -55,6 +59,10 @@
<Project>{36528547-53DC-46CD-8C97-1BAE69262B00}</Project>
<Name>Network.Dns</Name>
</ProjectReference>
<ProjectReference Include="..\Network\Network.csproj">
<Project>{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}</Project>
<Name>Network %28Network\Network%29</Name>
</ProjectReference>
<ProjectReference Include="..\SD\Network.ZeroConf.csproj">
<Project>{2B2D41E0-DBC7-4075-873C-394D02448281}</Project>
<Name>Network.ZeroConf</Name>

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -6,6 +6,7 @@ using Network.Rest;
using System.IO;
using System.Xml.Linq;
using System.Net;
using Network;
namespace DLNA.ContentDirectory
{
@ -13,7 +14,7 @@ namespace DLNA.ContentDirectory
{
public Browse(string connectionString) : base(connectionString) { }
public override void Initialize(HttpRequest request)
public override Command<HttpRequestEventArgs, HttpRequest, HttpResponse> Initialize(HttpRequest request, IServiceProvider provider)
{
throw new NotImplementedException();
}
@ -41,7 +42,7 @@ namespace DLNA.ContentDirectory
return request;
}
public override void Execute(RequestEventArgs e)
public override void Execute(HttpRequestEventArgs e)
{
throw new NotImplementedException();
}

View File

@ -12,6 +12,10 @@
<AssemblyName>Network.UPnP.DLNA</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -50,10 +54,14 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Rest\Network.Rest.csproj">
<Project>{3FFE9D8C-3914-4DD1-BB7C-8D4359216806}</Project>
<ProjectReference Include="..\Network.Rest\Network.Rest.csproj">
<Project>{13A68F9C-F095-409E-A97D-A05FFCDCE210}</Project>
<Name>Network.Rest</Name>
</ProjectReference>
<ProjectReference Include="..\Network\Network.csproj">
<Project>{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}</Project>
<Name>Network %28Network\Network%29</Name>
</ProjectReference>
<ProjectReference Include="..\UPnP\Network.UPnP.Services.csproj">
<Project>{39E23211-B902-4FE9-8A61-264F81D63864}</Project>
<Name>Network.UPnP.Services</Name>

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -5,7 +5,7 @@ using System.Text;
namespace Network.Dns
{
public class Answer
public class Answer: IResponse
{
public DomainName DomainName { get; set; }
public Type Type { get; set; }
@ -13,39 +13,39 @@ namespace Network.Dns
public uint Ttl { get; set; }
public ResponseData ResponseData { get; set; }
public byte[] ToBytes()
public byte[] GetBytes()
{
List<byte> bytes = new List<byte>();
bytes.AddRange(DomainName.ToBytes());
bytes.AddRange(Message.ToBytes((ushort)Type));
bytes.AddRange(Message.ToBytes((ushort)Class));
bytes.AddRange(Message.ToBytes(Ttl));
bytes.AddRange(ResponseData.ToBytes());
return bytes.ToArray();
}
public static Answer FromBytes(byte[] bytes, ref int index)
{
Answer a = new Answer();
a.DomainName = DomainName.FromBytes(bytes, ref index);
ushort s;
Message.FromBytes(bytes, index, out s);
a.Type = (Type)s;
index += 2;
Message.FromBytes(bytes, index, out s);
a.Class = (Class)s;
index += 2;
uint ttl;
Message.FromBytes(bytes, index, out ttl);
a.Ttl = ttl;
index += 4;
a.ResponseData = ResponseData.FromBytes(a.Type, bytes, ref index);
return a;
return BinaryHelper.GetBytes(this);
}
public override string ToString()
{
return string.Format("{0}, Type: {1}, Class: {2}, TTL: {3} = {4}", DomainName, Type, Class, Ttl, ResponseData);
}
internal static Answer Get(System.IO.BinaryReader reader)
{
Answer a = new Answer();
a.DomainName = DomainName.Get(reader);
ushort s;
Message.FromBytes(reader.ReadBytes(2), out s);
a.Type = (Type)s;
Message.FromBytes(reader.ReadBytes(2), out s);
a.Class = (Class)s;
uint ttl;
Message.FromBytes(reader.ReadBytes(4), out ttl);
a.Ttl = ttl;
a.ResponseData = ResponseData.Get(a.Type, reader);
return a;
}
public void WriteTo(System.IO.BinaryWriter writer)
{
DomainName.WriteTo(writer);
writer.Write(Message.ToBytes((ushort)Type));
writer.Write(Message.ToBytes((ushort)Class));
writer.Write(Message.ToBytes(Ttl));
ResponseData.WriteTo(writer);
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Network.Dns
{
class BackReferenceBinaryReader : BinaryReader
{
public BackReferenceBinaryReader(Stream input)
: base(input)
{
}
public BackReferenceBinaryReader(Stream input, Encoding encoding)
: base(input, encoding)
{
}
SortedDictionary<int, object> registeredElements = new SortedDictionary<int, object>();
public T Get<T>(int p)
{
return (T)registeredElements[p];
}
public void Register(int p, object value)
{
registeredElements.Add(p,value);
}
}
}

View File

@ -124,7 +124,12 @@ namespace Network.Dns
/// <summary>
/// the location of the server(s) for a specific protocol and domain
/// </summary>
SRV = 33
SRV = 33,
/// <summary>
/// EDNS0 option
/// </summary>
OPT=41
}
public enum QType

40
DnsResolver/DnsServer.cs Normal file
View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
namespace Network.Dns
{
public class DnsServer : Server<Message, Message>
{
public DnsServer(ushort port)
: base(port)
{
}
public DnsServer(IPAddress address, ushort port)
: base(address, port)
{
}
public DnsServer(IPEndPoint host)
: base(host)
{
}
public DnsServer()
: this(53)
{
}
protected override RequestEventArgs<Message, Message> GetEventArgs(Message request)
{
return new RequestEventArgs<Message, Message>() { Request = request };
}
}
}

View File

@ -2,10 +2,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Network.Dns
{
public class DomainName : List<string>
public class DomainName : List<string>, IResponse
{
public DomainName() { }
@ -24,6 +25,20 @@ namespace Network.Dns
return bytes.ToArray();
}
public ushort GetByteCount()
{
ushort result = 1;
foreach (string label in this)
{
if (label.Length == 0)
break;
int bytes = Encoding.UTF8.GetByteCount(label);
result += (ushort)(bytes + 1);
//labels.Add(new KeyValuePair<byte[], byte>(bytes, (byte)bytes.Length));
//totalLength += (ushort)(bytes.Length + 1);
}
return result;
}
public static DomainName FromBytes(byte[] bytes, ref int index)
{
@ -74,5 +89,69 @@ namespace Network.Dns
dn.AddRange(s.Split('.'));
return dn;
}
#region IResponse Members
public void WriteTo(BinaryWriter writer)
{
//ushort totalLength = 0;
//List<KeyValuePair<byte[], byte>> labels = new List<KeyValuePair<byte[], byte>>();
foreach (string label in this)
{
if (label.Length == 0)
break;
byte[] bytes = Encoding.UTF8.GetBytes(label);
//labels.Add(new KeyValuePair<byte[], byte>(bytes, (byte)bytes.Length));
//totalLength += (ushort)(bytes.Length + 1);
writer.Write((byte)bytes.Length);
writer.Write(bytes);
}
writer.Write((byte)0);
//writer.Write(totalLength);
//foreach (var label in labels)
//{
// writer.Write(label.Value);
// writer.Write(label.Key);
//}
}
public byte[] GetBytes()
{
return BinaryHelper.GetBytes(this);
}
#endregion
public static DomainName Get(BinaryReader reader)
{
byte stringLength = reader.ReadByte();
if (stringLength >> 6 == 3)
{
if (!(reader is BackReferenceBinaryReader))
throw new NotSupportedException("The given binary reader does not support back reference");
//In case of pointer
ushort ptr;
Message.FromBytes(new byte[] { (byte)(stringLength - (3 << 6)), reader.ReadByte() }, out ptr);
return ((BackReferenceBinaryReader)reader).Get<DomainName>(ptr);
}
else
{
DomainName dn = new DomainName();
if (reader is BackReferenceBinaryReader)
((BackReferenceBinaryReader)reader).Register((int)reader.BaseStream.Position - 1, dn);
//stringLength = reader.ReadByte();
if (stringLength != 0)
{
dn.Add(Encoding.UTF8.GetString(reader.ReadBytes(stringLength)));
//dn.Add(Encoding.UTF8.GetString(bytes, index + 1, bytes[index]));
dn.AddRange(DomainName.Get(reader));
}
//else
// index++;
return dn;
}
}
}
}

View File

@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
namespace Network.Dns
{
public class Message
public class Message : IRequest<Message>, IResponse
{
public Message()
{
@ -50,41 +51,47 @@ namespace Network.Dns
public byte[] ToByteArray()
{
List<byte> bytes = new List<byte>();
//ID
bytes.AddRange(ToBytes(ID));
//Qr, Opcode, Aa, Tc, Rd
byte b = 0;
b += (byte)QueryResponse;
b = (byte)(b << 4);
b += (byte)OpCode;
b = (byte)(b << 1);
b += (AuthoritativeAnswer) ? (byte)1 : (byte)0;
b = (byte)(b << 1);
b += (Truncated) ? (byte)1 : (byte)0;
b = (byte)(b << 1);
b += (RecursionDesired) ? (byte)1 : (byte)0;
bytes.Add(b);
using (MemoryStream stream = new MemoryStream())
{
WriteTo(new BinaryWriter(stream));
return stream.ToArray();
}
//Ra, Z, Rcode
b = 0;
b += (RecursionAvailable) ? (byte)1 : (byte)0;
b = (byte)(b << 7);
b += (byte)ResponseCode;
bytes.Add(b);
bytes.AddRange(ToBytes(QuestionEntries));
bytes.AddRange(ToBytes(AnswerEntries));
bytes.AddRange(ToBytes(AuthorityEntries));
bytes.AddRange(ToBytes(AdditionalEntries));
foreach (Question q in Questions)
bytes.AddRange(q.ToBytes());
foreach (Answer a in Answers)
bytes.AddRange(a.ToBytes());
foreach (Answer a in Authorities)
bytes.AddRange(a.ToBytes());
foreach (Answer a in Additionals)
bytes.AddRange(a.ToBytes());
return bytes.ToArray();
//List<byte> bytes = new List<byte>();
////ID
//bytes.AddRange(ToBytes(ID));
////Qr, Opcode, Aa, Tc, Rd
//byte b = 0;
//b += (byte)QueryResponse;
//b = (byte)(b << 4);
//b += (byte)OpCode;
//b = (byte)(b << 1);
//b += (AuthoritativeAnswer) ? (byte)1 : (byte)0;
//b = (byte)(b << 1);
//b += (Truncated) ? (byte)1 : (byte)0;
//b = (byte)(b << 1);
//b += (RecursionDesired) ? (byte)1 : (byte)0;
//bytes.Add(b);
////Ra, Z, Rcode
//b = 0;
//b += (RecursionAvailable) ? (byte)1 : (byte)0;
//b = (byte)(b << 7);
//b += (byte)ResponseCode;
//bytes.Add(b);
//bytes.AddRange(ToBytes(QuestionEntries));
//bytes.AddRange(ToBytes(AnswerEntries));
//bytes.AddRange(ToBytes(AuthorityEntries));
//bytes.AddRange(ToBytes(AdditionalEntries));
//foreach (Question q in Questions)
// bytes.AddRange(q.ToBytes());
//foreach (Answer a in Answers)
// bytes.AddRange(a.ToBytes());
//foreach (Answer a in Authorities)
// bytes.AddRange(a.ToBytes());
//foreach (Answer a in Additionals)
// bytes.AddRange(a.ToBytes());
//return bytes.ToArray();
}
@ -145,47 +152,6 @@ namespace Network.Dns
public IList<Answer> Authorities { get; set; }
public IList<Answer> Additionals { get; set; }
public static Message FromBytes(byte[] bytes)
{
Message m = new Message();
ushort id;
int index = 0;
FromBytes(bytes, out id);
m.ID = id;
index++; index++;
byte b = bytes[index++];
//Qr, Opcode, Aa, Tc, Rd
m.RecursionDesired = (b % 2) == 1;
b = (byte)(b >> 1);
m.Truncated = (b % 2) == 1;
b = (byte)(b >> 1);
m.AuthoritativeAnswer = (b % 2) == 1;
b = (byte)(b >> 1);
int opCodeNumber = b % 16;
m.OpCode = (OpCode)opCodeNumber;
b = (byte)(b >> 4);
m.QueryResponse = (Qr)b;
//Ra, Z, Rcode
b = bytes[index++];
m.RecursionAvailable = b > 127;
b = (byte)((b << 1) >> 1);
m.ResponseCode = (ResponseCode)b;
ushort questionEntryCount, answerEntryCount, authorityEntryCount, additionalEntryCount;
FromBytes(new byte[] { bytes[index++], bytes[index++] }, out questionEntryCount);
FromBytes(new byte[] { bytes[index++], bytes[index++] }, out answerEntryCount);
FromBytes(new byte[] { bytes[index++], bytes[index++] }, out authorityEntryCount);
FromBytes(new byte[] { bytes[index++], bytes[index++] }, out additionalEntryCount);
for (int i = 0; i < questionEntryCount; i++)
m.Questions.Add(Question.FromBytes(bytes, ref index));
for (int i = 0; i < answerEntryCount; i++)
m.Answers.Add(Answer.FromBytes(bytes, ref index));
for (int i = 0; i < authorityEntryCount; i++)
m.Authorities.Add(Answer.FromBytes(bytes, ref index));
for (int i = 0; i < additionalEntryCount; i++)
m.Additionals.Add(Answer.FromBytes(bytes, ref index));
return m;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
@ -207,5 +173,124 @@ namespace Network.Dns
return sb.ToString();
}
#region IResponse Members
public void WriteTo(BinaryWriter writer)
{
//ID
writer.Write(Message.ToBytes(ID));
//Qr, Opcode, Aa, Tc, Rd
byte b = 0;
b += (byte)QueryResponse;
b = (byte)(b << 4);
b += (byte)OpCode;
b = (byte)(b << 1);
b += (AuthoritativeAnswer) ? (byte)1 : (byte)0;
b = (byte)(b << 1);
b += (Truncated) ? (byte)1 : (byte)0;
b = (byte)(b << 1);
b += (RecursionDesired) ? (byte)1 : (byte)0;
writer.Write(b);
//Ra, Z, Rcode
b = 0;
b += (RecursionAvailable) ? (byte)1 : (byte)0;
b = (byte)(b << 7);
b += (byte)ResponseCode;
writer.Write(b);
writer.Write(Message.ToBytes(QuestionEntries));
writer.Write(Message.ToBytes(AnswerEntries));
writer.Write(Message.ToBytes(AuthorityEntries));
writer.Write(Message.ToBytes(AdditionalEntries));
foreach (Question q in Questions)
q.WriteTo(writer);
foreach (Answer a in Answers)
a.WriteTo(writer);
foreach (Answer a in Authorities)
a.WriteTo(writer);
foreach (Answer a in Additionals)
a.WriteTo(writer);
}
public byte[] GetBytes()
{
return this.ToByteArray();
}
#endregion
#region IRequest<Message> Members
public Message GetRequest(BinaryReader reader)
{
if (!(reader is BackReferenceBinaryReader))
reader = new BackReferenceBinaryReader(reader.BaseStream, Encoding.BigEndianUnicode);
Message m = new Message();
ushort id;
int index = 0;
Message.FromBytes(reader.ReadBytes(2), out id);
//FromBytes(bytes, out id);
m.ID = id;
index++; index++;
byte b = reader.ReadByte();
//byte b = bytes[index++];
//Qr, Opcode, Aa, Tc, Rd
m.RecursionDesired = (b % 2) == 1;
b = (byte)(b >> 1);
m.Truncated = (b % 2) == 1;
b = (byte)(b >> 1);
m.AuthoritativeAnswer = (b % 2) == 1;
b = (byte)(b >> 1);
int opCodeNumber = b % 16;
m.OpCode = (OpCode)opCodeNumber;
b = (byte)(b >> 4);
m.QueryResponse = (Qr)b;
//Ra, Z, Rcode
b = reader.ReadByte();
//b = bytes[index++];
m.RecursionAvailable = b > 127;
b = (byte)((b << 1) >> 1);
m.ResponseCode = (ResponseCode)b;
ushort questionEntryCount, answerEntryCount, authorityEntryCount, additionalEntryCount;
Message.FromBytes(reader.ReadBytes(2), out questionEntryCount);
Message.FromBytes(reader.ReadBytes(2), out answerEntryCount);
Message.FromBytes(reader.ReadBytes(2), out authorityEntryCount);
Message.FromBytes(reader.ReadBytes(2), out additionalEntryCount);
//FromBytes(new byte[] { bytes[index++], bytes[index++] }, out questionEntryCount);
//FromBytes(new byte[] { bytes[index++], bytes[index++] }, out answerEntryCount);
//FromBytes(new byte[] { bytes[index++], bytes[index++] }, out authorityEntryCount);
//FromBytes(new byte[] { bytes[index++], bytes[index++] }, out additionalEntryCount);
for (int i = 0; i < questionEntryCount; i++)
m.Questions.Add(Question.Get(reader));
for (int i = 0; i < answerEntryCount; i++)
m.Answers.Add(Answer.Get(reader));
for (int i = 0; i < authorityEntryCount; i++)
m.Authorities.Add(Answer.Get(reader));
for (int i = 0; i < additionalEntryCount; i++)
m.Additionals.Add(Answer.Get(reader));
return m;
}
public Message GetRequest(byte[] requestBytes)
{
using (MemoryStream ms=new MemoryStream(requestBytes))
{
ms.Position = 0;
return GetRequest(new BinaryReader(ms));
}
}
#endregion
public Message Clone()
{
using (MemoryStream ms = new MemoryStream())
{
WriteTo(new BinaryWriter(ms));
ms.Position = 0;
return GetRequest(new BinaryReader(ms));
}
}
}
}

View File

@ -12,6 +12,10 @@
<AssemblyName>DnsResolver</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -46,6 +50,10 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Answer.cs" />
<Compile Include="BackReferenceBinaryReader.cs" />
<Compile Include="DnsServer.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="DomainName.cs" />
<Compile Include="EndPoint.cs" />
<Compile Include="Message.cs" />
@ -54,6 +62,12 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ResponseData.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Network\Network.csproj">
<Project>{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}</Project>
<Name>Network %28Network\Network%29</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.IO;
namespace Network.Dns
{
public class Question
public class Question : IResponse
{
private Question()
{
@ -39,6 +40,8 @@ namespace Network.Dns
public QType Type { get; set; }
public QClass Class { get; set; }
public bool CacheFlush { get; set; }
public byte[] ToBytes()
{
List<byte> bytes = new List<byte>();
@ -71,5 +74,34 @@ namespace Network.Dns
sb.AppendFormat(" QClass : {0}", Class);
return sb.ToString();
}
#region IResponse Members
public void WriteTo(BinaryWriter writer)
{
DomainName.WriteTo(writer);
writer.Write(Message.ToBytes((ushort)Type));
writer.Write(Message.ToBytes((ushort)Class));
}
public byte[] GetBytes()
{
return BinaryHelper.GetBytes(this);
}
#endregion
public static Question Get(BinaryReader reader)
{
Question q = new Question();
q.DomainName = DomainName.Get(reader);
ushort s;
Message.FromBytes(reader.ReadBytes(2), out s);
q.Type = (QType)s;
Message.FromBytes(reader.ReadBytes(2), out s);
q.Class = (QClass)((ushort)(s << 1) >> 1);
q.CacheFlush = ((ushort)q.Class) != s;
return q;
}
}
}

View File

@ -3,20 +3,21 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
namespace Network.Dns
{
public abstract class ResponseData
{
public abstract byte[] ToBytes();
public abstract void WriteTo(System.IO.BinaryWriter writer);
internal static ResponseData FromBytes(Type type, byte[] bytes, ref int index)
internal static ResponseData Get(Type type, System.IO.BinaryReader reader)
{
switch (type)
{
case Type.A:
case Type.AAAA:
return HostAddress.FromBytes(bytes, ref index);
return HostAddress.Get(reader);
break;
case Type.NS:
break;
@ -25,7 +26,7 @@ namespace Network.Dns
case Type.MF:
break;
case Type.CNAME:
return CName.FromBytes(bytes, ref index);
return CName.Get(reader);
break;
case Type.SOA:
break;
@ -40,7 +41,7 @@ namespace Network.Dns
case Type.WKS:
break;
case Type.PTR:
return Ptr.FromBytes(bytes, ref index);
return Ptr.Get(reader);
break;
case Type.HINFO:
break;
@ -49,15 +50,16 @@ namespace Network.Dns
case Type.MX:
break;
case Type.TXT:
return Txt.FromBytes(bytes, ref index);
return Txt.Get(reader);
break;
case Type.SRV:
return Srv.FromBytes(bytes, ref index);
return Srv.Get(reader);
break;
default:
break;
}
throw new NotImplementedException(string.Format("Cannot read {0} response", type));
//throw new NotImplementedException(string.Format("Cannot read {0} response", type));
return null;
}
}
@ -65,22 +67,18 @@ namespace Network.Dns
{
public string CNAME { get; set; }
public override byte[] ToBytes()
public override void WriteTo(System.IO.BinaryWriter writer)
{
List<byte> bytes = new List<byte>();
bytes.AddRange(Message.ToBytes((ushort)Encoding.UTF8.GetByteCount(CNAME)));
bytes.AddRange(Encoding.UTF8.GetBytes(CNAME));
return bytes.ToArray();
writer.Write(Message.ToBytes((ushort)Encoding.UTF8.GetByteCount(CNAME)));
writer.Write(Encoding.UTF8.GetBytes(CNAME));
}
internal static CName FromBytes(byte[] bytes, ref int index)
internal static CName Get(BinaryReader reader)
{
ushort byteCount;
Message.FromBytes(bytes, index, out byteCount);
index += 2;
Message.FromBytes(reader.ReadBytes(2), out byteCount);
CName cName = new CName();
cName.CNAME = Encoding.UTF8.GetString(bytes, index + 2, byteCount);
index += byteCount;
cName.CNAME = Encoding.UTF8.GetString(reader.ReadBytes(byteCount), 0, byteCount);
return cName;
}
}
@ -89,24 +87,20 @@ namespace Network.Dns
{
public IPAddress Address { get; set; }
internal static HostAddress FromBytes(byte[] bytes, ref int index)
internal static HostAddress Get(BinaryReader reader)
{
ushort byteCount;
Message.FromBytes(bytes, index, out byteCount);
index += 2;
Message.FromBytes(reader.ReadBytes(2), out byteCount);
HostAddress ha = new HostAddress();
ha.Address = new IPAddress(bytes.Skip(index).Take(byteCount).ToArray());
index += byteCount;
ha.Address = new IPAddress(reader.ReadBytes(byteCount));
return ha;
}
public override byte[] ToBytes()
public override void WriteTo(System.IO.BinaryWriter writer)
{
List<byte> bytes = new List<byte>();
byte[] address = Address.GetAddressBytes();
bytes.AddRange(Message.ToBytes((ushort)address.Length));
bytes.AddRange(address);
return bytes.ToArray();
writer.Write(Message.ToBytes((ushort)address.Length));
writer.Write(address);
}
public override string ToString()
@ -118,21 +112,20 @@ namespace Network.Dns
{
public DomainName DomainName { get; set; }
public override byte[] ToBytes()
public override void WriteTo(System.IO.BinaryWriter writer)
{
List<byte> bytes = new List<byte>();
bytes.AddRange(DomainName.ToBytes());
bytes.InsertRange(0, Message.ToBytes((ushort)bytes.Count));
return bytes.ToArray();
writer.Write(Message.ToBytes(DomainName.GetByteCount()));
DomainName.WriteTo(writer);
}
internal static Ptr FromBytes(byte[] bytes, ref int index)
internal static Ptr Get(BinaryReader reader)
{
Ptr p = new Ptr();
ushort byteCount;
Message.FromBytes(bytes, index, out byteCount);
index += 2;
p.DomainName = DomainName.FromBytes(bytes, ref index);
//useless datalength
Message.FromBytes(reader.ReadBytes(2), out byteCount);
p.DomainName = DomainName.Get(reader);
//index += byteCount;
return p;
}
@ -140,15 +133,12 @@ namespace Network.Dns
public class Srv : ResponseData
{
public override byte[] ToBytes()
public override void WriteTo(System.IO.BinaryWriter writer)
{
List<byte> bytes = new List<byte>();
bytes.AddRange(Message.ToBytes(Priority));
bytes.AddRange(Message.ToBytes(Weight));
bytes.AddRange(Message.ToBytes(Port));
bytes.AddRange(Target.ToBytes());
bytes.InsertRange(0, Message.ToBytes((ushort)bytes.Count));
return bytes.ToArray();
writer.Write(Message.ToBytes(Priority));
writer.Write(Message.ToBytes(Weight));
writer.Write(Message.ToBytes(Port));
Target.WriteTo(writer);
}
public ushort Priority { get; set; }
@ -156,23 +146,19 @@ namespace Network.Dns
public ushort Port { get; set; }
public DomainName Target { get; set; }
internal static Srv FromBytes(byte[] bytes, ref int index)
internal static Srv Get(BinaryReader reader)
{
Srv srv = new Srv();
ushort s;
//Useless Datalength
Message.FromBytes(bytes, index, out s);
index += 2;
Message.FromBytes(bytes, index, out s);
index += 2;
reader.ReadBytes(2);
Message.FromBytes(reader.ReadBytes(2), out s);
srv.Priority = s;
Message.FromBytes(bytes, index, out s);
index += 2;
Message.FromBytes(reader.ReadBytes(2), out s);
srv.Weight = s;
Message.FromBytes(bytes, index, out s);
index += 2;
Message.FromBytes(reader.ReadBytes(2), out s);
srv.Port = s;
srv.Target = DomainName.FromBytes(bytes, ref index);
srv.Target = DomainName.Get(reader);
return srv;
}
}
@ -184,20 +170,25 @@ namespace Network.Dns
Properties = new Dictionary<string, string>();
}
public override byte[] ToBytes()
public override void WriteTo(System.IO.BinaryWriter writer)
{
ushort length = 0;
List<byte> bytes = new List<byte>();
List<KeyValuePair<byte[], byte>> bytes = new List<KeyValuePair<byte[], byte>>();
foreach (KeyValuePair<string, string> kvp in Properties)
{
byte[] kvpBytes = Encoding.UTF8.GetBytes(kvp.Key + "=" + kvp.Value);
bytes.Add((byte)kvpBytes.Length);
bytes.AddRange(kvpBytes);
bytes.Add(new KeyValuePair<byte[], byte>(kvpBytes, (byte)kvpBytes.Length));
//writer.Write((byte)kvpBytes.Length);
//writer.Write(kvpBytes);
length += (ushort)kvpBytes.Length;
length++;
}
bytes.InsertRange(0, Message.ToBytes(length));
return bytes.ToArray();
writer.Write(Message.ToBytes(length));
foreach (var properties in bytes)
{
writer.Write(properties.Value);
writer.Write(properties.Key);
}
}
public const string True = "true";
@ -226,18 +217,17 @@ namespace Network.Dns
public IDictionary<string, string> Properties { get; set; }
internal static Txt FromBytes(byte[] bytes, ref int index)
internal static Txt Get(BinaryReader reader)
{
Txt txt = new Txt();
ushort byteCount;
ushort byteCount, byteRead = 0;
//Useless Datalength
Message.FromBytes(bytes, index, out byteCount);
index += 2;
int stop = index + byteCount;
while (index < stop)
Message.FromBytes(reader.ReadBytes(2), out byteCount);
while (byteRead < byteCount)
{
txt.AddProperty(Encoding.UTF8.GetString(bytes, index + 1, bytes[index]));
index += bytes[index] + 1;
byte propertyLength = reader.ReadByte();
byteRead += (ushort)(propertyLength + 1);
txt.AddProperty(Encoding.UTF8.GetString(reader.ReadBytes(propertyLength), 0, propertyLength));
}
return txt;
}

View File

@ -13,6 +13,10 @@
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<StartupObject>MEF.Bonjour.Tests.Program</StartupObject>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -12,6 +12,10 @@
<AssemblyName>MEF.Bonjour</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -13,6 +13,10 @@
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<StartupObject>Network.Bonjour.Services.Pear.AirDiskService</StartupObject>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -63,6 +67,10 @@
<Project>{36528547-53DC-46CD-8C97-1BAE69262B00}</Project>
<Name>Network.Dns</Name>
</ProjectReference>
<ProjectReference Include="..\Network\Network.csproj">
<Project>{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}</Project>
<Name>Network %28Network\Network%29</Name>
</ProjectReference>
<ProjectReference Include="..\SD\Network.ZeroConf.csproj">
<Project>{2B2D41E0-DBC7-4075-873C-394D02448281}</Project>
<Name>Network.ZeroConf</Name>

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -12,6 +12,10 @@
<AssemblyName>Network.Rest.MEF</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -53,13 +57,17 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Rest\Network.Rest.csproj">
<Project>{3FFE9D8C-3914-4DD1-BB7C-8D4359216806}</Project>
<Name>Network.Rest</Name>
</ProjectReference>
<WCFMetadata Include="Service References\" />
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Service References\" />
<ProjectReference Include="..\Network.Rest\Network.Rest.csproj">
<Project>{13A68F9C-F095-409E-A97D-A05FFCDCE210}</Project>
<Name>Network.Rest</Name>
</ProjectReference>
<ProjectReference Include="..\Network\Network.csproj">
<Project>{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}</Project>
<Name>Network %28Network\Network%29</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -30,7 +30,7 @@ namespace Network.Rest.MEF
public RestServer(ushort port)
: base(port)
{
this.RequestReceived += new EventHandler<RequestEventArgs>(RestServer_RequestReceived);
this.HttpRequestReceived += new EventHandler<HttpRequestEventArgs>(RestServer_RequestReceived);
batch = new CompositionBatch();
batch.AddPart(this);
}
@ -42,7 +42,7 @@ namespace Network.Rest.MEF
base.OnStart();
}
void RestServer_RequestReceived(object sender, RequestEventArgs e)
void RestServer_RequestReceived(object sender, HttpRequestEventArgs e)
{
Command c = commands.Where(command => command.Metadata["Method"].ToString() == e.Request.Method && command.Metadata.ContainsKey("UriConstraint") ? Regex.IsMatch(e.Request.Uri, command.Metadata["UriConstraint"].ToString()) : true).Single().GetExportedObject();
c.Execute(e);

57
Network.Rest/Command.cs Normal file
View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Net;
namespace Network.Rest
{
public abstract class Command : Command<HttpRequestEventArgs, HttpRequest, HttpResponse>
{
public Command(string connectionString)
{
Uri = new Uri(connectionString);
}
public Command()
{
}
public Uri Uri { get; protected set; }
protected string Method { get; set; }
protected override HttpRequest BuildRequest()
{
HttpRequest request = new HttpRequest(Uri);
request.KeepAlive = true;
request.ContentType = "text/xml";
request.Method = Method;
return request;
}
protected abstract HttpRequest GetRequest();
public override HttpResponse GetResponse(bool responseExpected)
{
HttpRequest request = GetRequest();
return (HttpResponse)request.GetResponse(responseExpected);
}
XmlDocument doc = new XmlDocument();
bool docLoaded = false;
public XmlDocument GetXmlResponse()
{
if (!docLoaded)
{
HttpResponse response = GetResponse();
docLoaded = true;
doc.Load(response.Body);
}
return doc;
}
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace Network.Rest
{
public class CommandFactory : CommandFactory<HttpRequestEventArgs, HttpRequest, HttpResponse>
{
protected override Command<HttpRequestEventArgs, HttpRequest, HttpResponse> GetCommandInternal(HttpRequest request)
{
IDictionary<Regex, Type> possibleCommands = registeredCommands[request.Method];
foreach (KeyValuePair<Regex, Type> command in possibleCommands)
{
if (command.Key.IsMatch(request.Uri))
return (Command<HttpRequestEventArgs, HttpRequest, HttpResponse>)Activator.CreateInstance(command.Value);
}
throw new NotSupportedException("No command have been registered for this kind of request");
}
}
}

View File

@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
namespace Network.Rest
{
public class HttpMessage
{
public HttpMessage()
{
Headers = new Dictionary<string, string>();
Encoding = Encoding.UTF8;
Uri = "*";
Body = new MemoryStream();
}
public HttpMessage(string uriString) : this(new Uri(uriString)) { }
public HttpMessage(Uri uri)
: this()
{
Uri = uri.PathAndQuery;
if (uri.Port > 0)
Host = uri.Host + ":" + uri.Port;
else
Host = uri.Host;
}
public MemoryStream Body { get; protected set; }
public string Uri { get; set; }
public IDictionary<string, string> Headers { get; set; }
public Encoding Encoding { get; set; }
public virtual int ContentLength
{
get
{
if (Headers.ContainsKey("Content-Length"))
return int.Parse(Headers["Content-Length"]);
return 0;
}
set
{
Headers["Content-Length"] = value.ToString();
}
}
public string Host
{
get
{
if (Headers.ContainsKey("Host"))
return Headers["Host"];
return null;
}
set
{
if (Headers.ContainsKey("Host"))
Headers["Host"] = value;
else
Headers.Add("Host", value);
}
}
public HttpVersion HttpVersion { get; set; }
public virtual byte[] GetBytes()
{
return Encoding.GetBytes(this.ToString());
}
protected const char SPACE = ' ';
protected void ReadHeaders(TextReader reader)
{
string line;
while (!string.IsNullOrEmpty(line = reader.ReadLine()))
{
string[] header = line.Split(':');
Headers.Add(header[0], line.Substring(header[0].Length + 1));
}
}
}
public enum HttpVersion
{
HTTP11
}
}

166
Network.Rest/HttpRequest.cs Normal file
View File

@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.IO;
using System.Net.Sockets;
namespace Network.Rest
{
public class HttpRequest : HttpMessage, IRequest<HttpRequest>
{
public HttpRequest() { }
public HttpRequest(string uriString) : base(uriString) { }
public HttpRequest(Uri uri) : base(uri) { }
public string Method { get; set; }
public override int ContentLength
{
get
{
if (Body.Length > 0 && Headers.ContainsKey("Content-Length"))
return (int)Body.Length;
return base.ContentLength;
}
set
{
base.ContentLength = value;
}
}
public bool KeepAlive
{
get { return Headers["KeepAlive"] == "true"; }
set { Headers["KeepAlive"] = value.ToString(); }
}
public string ContentType
{
get { return (string)Headers["Content-Type"]; }
set { Headers["Content-Type"] = value; }
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(Method);
sb.Append(SPACE);
sb.Append(Uri);
sb.Append(SPACE);
switch (HttpVersion)
{
case HttpVersion.HTTP11:
sb.Append("HTTP/1.1");
break;
default:
break;
}
sb.AppendLine();
if (Host != null)
sb.AppendLine(string.Format("Host: {0}", Host));
if (Body.Length > 0)
Headers["Content-Length"] = Body.Length.ToString();
foreach (KeyValuePair<string, string> header in Headers)
{
if (header.Key != "Host")
sb.AppendLine(string.Format("{0}: {1}", header.Key, header.Value));
}
sb.AppendLine();
if (Body.Length > 0)
{
Body.Seek(0, SeekOrigin.Begin);
StreamReader reader = new StreamReader(Body);
sb.Append(reader.ReadToEnd());
//reader.Close();
sb.AppendLine();
sb.AppendLine();
}
return sb.ToString();
}
public TransportProtocol Protocol { get; set; }
public HttpResponse GetResponse(bool expectResponse)
{
Uri uri = new Uri("http://" + Host + Uri);
if (Protocol == TransportProtocol.TCP)
{
TcpClient client = new TcpClient();
client.Connect(uri.Host, uri.Port != 0 ? uri.Port : 80);
//Uri = Uri.Substring(Uri.IndexOf('/', Uri.IndexOf(uri.Host)));
byte[] requestBytes = GetBytes();
Uri = uri.ToString();
client.GetStream().Write(requestBytes, 0, requestBytes.Length);
if (!expectResponse)
return null;
MemoryStream stream = new MemoryStream();
NetworkStream clientStream = client.GetStream();
do
{
byte[] buffer = new byte[1024];
int lengthRead = clientStream.Read(buffer, 0, 1024);
stream.Write(buffer, 0, lengthRead);
} while (clientStream.DataAvailable);
return HttpResponse.FromBytes(stream.ToArray());
}
if (Protocol == TransportProtocol.UDP)
{
UdpClient client = new UdpClient();
client.Connect(uri.Host, uri.Port != 0 ? uri.Port : 80);
byte[] requestBytes = GetBytes();
client.Send(requestBytes, requestBytes.Length);
if (!expectResponse)
return null;
System.Net.IPEndPoint ep = new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0);
return HttpResponse.FromBytes(client.Receive(ref ep));
}
return null;
}
private static HttpRequest Parse(TextReader reader)
{
HttpRequest request = new HttpRequest();
//METHOD URI VERSION
string line = reader.ReadLine();
string[] firstLine = line.Split(SPACE);
request.Method = firstLine[0];
request.Uri = firstLine[1];
request.HttpVersion = HttpVersion.HTTP11;
request.ReadHeaders(reader);
request.Host = request.Host.Trim();
return request;
}
#region IRequest<HttpRequest> Members
public HttpRequest GetRequest(BinaryReader stream)
{
TextReader reader = new StreamReader(stream.BaseStream);
return Parse(reader);
}
public HttpRequest GetRequest(byte[] bytes)
{
return Parse(Encoding.UTF8.GetString(bytes));
}
public static HttpRequest Parse(string requestString)
{
StringReader reader = new StringReader(requestString);
return Parse(reader);
}
#endregion
}
public enum TransportProtocol
{
TCP,
UDP
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Network.Rest
{
public class HttpRequestEventArgs : RequestEventArgs<HttpRequest, HttpResponse>
{
public HttpRequestEventArgs()
{
Response = new HttpResponse();
}
}
}

View File

@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Xml;
namespace Network.Rest
{
public class HttpResponse : HttpMessage, IResponse
{
public HttpResponse()
{
ResponseCode = HttpStatusCode.OK;
}
public static HttpResponse FromBytes(byte[] bytes)
{
return Parse(Encoding.UTF8.GetString(bytes));
}
public HttpStatusCode ResponseCode { get; set; }
public string ResponseMessage { get; set; }
protected XmlDocument document = null;
public XmlDocument Document
{
get
{
if (document == null)
{
document = new XmlDocument();
if (Body.Length > 0)
document.Load(Body);
}
return document;
}
}
private static HttpResponse Parse(string responseString)
{
HttpResponse response = new HttpResponse();
StringReader reader = new StringReader(responseString);
string line = reader.ReadLine();
string[] firstLine = line.Split(' ');
//VERSION RESPONSECODE RESPONSEMESSAGE
response.HttpVersion = HttpVersion.HTTP11;
response.ResponseCode = (HttpStatusCode)int.Parse(firstLine[1]);
response.ResponseMessage = string.Join(" ", firstLine, 2, firstLine.Length - 2);
response.ReadHeaders(reader);
StreamWriter sw = new StreamWriter(response.Body);
sw.Write(reader.ReadToEnd());
response.Body.Seek(0, SeekOrigin.Begin);
return response;
}
public override string ToString()
{
using (MemoryStream ms = new MemoryStream())
{
WriteTo(new BinaryWriter(ms));
ms.Position = 0;
using (StreamReader reader = new StreamReader(ms))
{
return reader.ReadToEnd();
}
}
}
#region IResponse Members
public void WriteTo(BinaryWriter writer)
{
writer.Write(string.Format("HTTP/1.1 {0} {1}\n", (int)ResponseCode, ResponseMessage));
foreach (KeyValuePair<string, string> header in Headers)
{
if (header.Key != "Host")
writer.Write(string.Format("{0}:{1}\n", header.Key, header.Value));
}
writer.Write("\n");
Body.Seek(0, SeekOrigin.Begin);
Body.WriteTo(writer.BaseStream);
writer.Write("\n");
writer.Write("\n");
}
#endregion
}
}

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{13A68F9C-F095-409E-A97D-A05FFCDCE210}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Network.Rest</RootNamespace>
<AssemblyName>Network.Rest</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>rest.snk</AssemblyOriginatorKeyFile>
<TargetFrameworkSubset>
</TargetFrameworkSubset>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Command.cs" />
<Compile Include="CommandFactory.cs" />
<Compile Include="HttpRequestEventArgs.cs" />
<Compile Include="RestServer.cs" />
<Compile Include="HttpMessage.cs" />
<Compile Include="HttpRequest.cs" />
<Compile Include="HttpResponse.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Network\Network.csproj">
<Project>{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}</Project>
<Name>Network</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="rest.snk" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Network.Rest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Network.Rest")]
[assembly: AssemblyCopyright("Copyright © 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7bf45d0c-5b81-4d07-9655-68383357cfb1")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Net.Sockets;
namespace Network.Rest
{
public class RestServer : Server<HttpRequest, HttpResponse>
{
public RestServer()
: this(80)
{
}
public RestServer(ushort port)
: base(port)
{
}
public RestServer(IPAddress host, ushort port)
: base(host, port)
{
}
public RestServer(IPEndPoint host)
: base(host)
{
}
public event EventHandler<HttpRequestEventArgs> HttpRequestReceived;
protected override void OnRequestReceived(RequestEventArgs<HttpRequest, HttpResponse> rea)
{
base.OnRequestReceived(rea);
if (HttpRequestReceived != null)
HttpRequestReceived(this, (HttpRequestEventArgs)rea);
}
protected override RequestEventArgs<HttpRequest, HttpResponse> GetEventArgs(HttpRequest request)
{
return new HttpRequestEventArgs() { Request = request };
}
protected override void TreatTcp(RequestEventArgs<HttpRequest, HttpResponse> rea, System.Net.Sockets.TcpClient tcpClient)
{
try
{
base.TreatTcp(rea, tcpClient);
}
catch (NotImplementedException e)
{
ReplyError(tcpClient, e, HttpStatusCode.NotImplemented);
}
catch (Exception e)
{
ReplyError(tcpClient, e, HttpStatusCode.BadRequest);
}
}
protected override void TreatUdp(RequestEventArgs<HttpRequest, HttpResponse> rea, System.Net.IPEndPoint client)
{
try
{
base.TreatUdp(rea, client);
}
catch (NotImplementedException e)
{
ReplyError(client, e, HttpStatusCode.NotImplemented);
}
catch (Exception e)
{
ReplyError(client, e, HttpStatusCode.BadRequest);
}
}
private void ReplyError(TcpClient ep, Exception e, HttpStatusCode code)
{
HttpResponse response = new HttpResponse();
StreamWriter sw = new StreamWriter(response.Body);
sw.Write(e.ToString());
response.ResponseCode = HttpStatusCode.NotImplemented;
response.ResponseMessage = e.Message;
Send(response, ep);
}
private void ReplyError(IPEndPoint ep, Exception e, HttpStatusCode code)
{
HttpResponse response = new HttpResponse();
StreamWriter sw = new StreamWriter(response.Body);
sw.Write(e.ToString());
response.ResponseCode = HttpStatusCode.NotImplemented;
response.ResponseMessage = e.Message;
Send(response, ep);
}
}
}

3
Network.Rest/app.config Normal file
View File

@ -0,0 +1,3 @@
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>

BIN
Network.Rest/rest.snk Normal file

Binary file not shown.

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{61DB9D8D-F2EA-40DC-8F37-58092891A6A5}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Network.Tests</RootNamespace>
<AssemblyName>Network.Tests</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Network.Rest\Network.Rest.csproj">
<Project>{13A68F9C-F095-409E-A97D-A05FFCDCE210}</Project>
<Name>Network.Rest</Name>
</ProjectReference>
<ProjectReference Include="..\Network\Network.csproj">
<Project>{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}</Project>
<Name>Network</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
<Visible>False</Visible>
<ProductName>.NET Framework 2.0 %28x86%29</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
<Visible>False</Visible>
<ProductName>.NET Framework 3.0 %28x86%29</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

51
Network.Tests/Program.cs Normal file
View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Network.Rest;
using System.Threading;
using System.Net;
namespace Network.Tests
{
class Program
{
static void Main(string[] args)
{
RestServer server = new RestServer(IPAddress.Parse("224.0.0.224"), 53186);
server.RequestReceived += new EventHandler<RequestEventArgs<HttpRequest, HttpResponse>>(server_RequestReceived);
server.HttpRequestReceived += new EventHandler<HttpRequestEventArgs>(server_HttpRequestReceived);
server.StartUdp();
Console.WriteLine("Server Started");
//HttpRequest request = new HttpRequest("http://224.0.0.224:53186/Lucene/");
//request.Protocol = TransportProtocol.UDP;
//request.GetResponse(false);
//Thread.Sleep(1000);
//request = new HttpRequest("http://224.0.0.224:53186/Lucene/");
//request.Protocol = TransportProtocol.UDP;
//request.GetResponse(false);
//Thread.Sleep(10000);
//request = new HttpRequest("http://224.0.0.224:53186/Lucene/");
//request.Protocol = TransportProtocol.UDP;
//request.GetResponse(false);
//Thread.Sleep(30000);
//request = new HttpRequest("http://224.0.0.224:53186/Lucene/");
//request.Protocol = TransportProtocol.UDP;
//request.GetResponse(false);
Console.Read();
server.Stop();
Console.WriteLine("Server Stopped");
}
static void server_HttpRequestReceived(object sender, HttpRequestEventArgs e)
{
server_RequestReceived(sender, e);
Console.WriteLine(e.Request.ToString());
}
static void server_RequestReceived(object sender, RequestEventArgs<HttpRequest, HttpResponse> e)
{
Console.WriteLine("Request received from " + e.Host);
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Network.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Network.Tests")]
[assembly: AssemblyCopyright("Copyright © 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("152caa80-1b00-422a-b3d0-a9fa4767c124")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

52
Network/BinaryRequest.cs Normal file
View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Network
{
public class BinaryRequest : IRequest<BinaryRequest>
{
MemoryStream stream = new MemoryStream();
#region IRequest<BinaryRequest> Members
public BinaryRequest GetRequest(BinaryReader stream)
{
BinaryRequest request = new BinaryRequest();
byte[] buffer = new byte[1024];
int length = buffer.Length;
while (length > 0)
{
length = stream.Read(buffer, 0, buffer.Length);
request.stream.Write(buffer, 0, length);
}
return request;
}
public void WriteTo(System.IO.Stream stream)
{
this.stream.WriteTo(stream);
}
public byte[] GetBytes()
{
return stream.ToArray();
}
#endregion
#region IRequest<BinaryRequest> Members
public BinaryRequest GetRequest(byte[] requestBytes)
{
using (MemoryStream stream = new MemoryStream(requestBytes))
{
return GetRequest(new BinaryReader(stream));
}
}
#endregion
}
}

44
Network/BinaryResponse.cs Normal file
View File

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Network
{
public class BinaryResponse : IResponse
{
private MemoryStream stream;
public BinaryResponse()
{
stream = new MemoryStream();
}
#region IResponse Members
public void WriteTo(BinaryWriter target)
{
this.stream.Position = 0;
this.stream.WriteTo(target.BaseStream);
}
public byte[] GetBytes()
{
return stream.ToArray();
}
#endregion
}
public static class BinaryHelper
{
public static byte[] GetBytes(IResponse response)
{
using (MemoryStream stream = new MemoryStream())
{
response.WriteTo(new BinaryWriter(stream));
return stream.ToArray();
}
}
}
}

35
Network/Command.cs Normal file
View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Network
{
public abstract class Command<RequestEventArgsType, RequestType, ResponseType>
where RequestEventArgsType : RequestEventArgs<RequestType, ResponseType>
where ResponseType : IResponse
{
public Command()
{
}
public abstract Command<RequestEventArgsType, RequestType, ResponseType> Initialize(RequestType request, IServiceProvider server);
protected abstract RequestType BuildRequest();
public virtual ResponseType GetResponse()
{
return GetResponse(true);
}
public abstract ResponseType GetResponse(bool expectResponse);
public abstract void Execute(RequestEventArgsType e);
}
public abstract class Command<RequestType, ResponseType> :
Command<RequestEventArgs<RequestType, ResponseType>, RequestType, ResponseType>
where ResponseType : IResponse
{
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Network.Rest
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class CommandDescriptorAttribute : Attribute
{
public string Method { get; set; }
public string UriRegex { get; set; }
public CommandDescriptorAttribute(string method)
: base()
{
Method = method;
}
}
}

48
Network/CommandFactory.cs Normal file
View File

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace Network.Rest
{
public abstract class CommandFactory<EventArgs, RequestType, ResponseType>
where EventArgs : RequestEventArgs<RequestType, ResponseType>
where ResponseType : IResponse
where RequestType : IRequest<RequestType>, new()
{
protected IDictionary<string, IDictionary<Regex, Type>> registeredCommands = new Dictionary<string, IDictionary<Regex, Type>>();
public void RegisterCommand<T>()
where T : Command<EventArgs, RequestType, ResponseType>
{
foreach (CommandDescriptorAttribute attribute in typeof(T).GetCustomAttributes(typeof(CommandDescriptorAttribute), true))
{
IDictionary<Regex, Type> dict;
if (!registeredCommands.ContainsKey(attribute.Method))
{
dict = new Dictionary<Regex, Type>();
registeredCommands.Add(attribute.Method, dict);
}
else
dict = registeredCommands[attribute.Method];
if (string.IsNullOrEmpty(attribute.UriRegex))
dict.Add(new Regex("^/.*"), typeof(T));
}
}
public Command<EventArgs, RequestType, ResponseType> GetCommand(RequestType request, IServiceProvider server)
{
Command<EventArgs, RequestType, ResponseType> cmd = GetCommandInternal(request);
return cmd.Initialize(request, server);
//return cmd;
}
protected internal abstract Command<EventArgs, RequestType, ResponseType> GetCommandInternal(RequestType request);
public T GetCommand<T>(RequestType request, IServiceProvider server)
where T : Command<RequestEventArgs<RequestType, ResponseType>, RequestType, ResponseType>
{
return GetCommand(request, server) as T;
}
}
}

15
Network/IRequest.cs Normal file
View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Network
{
public interface IRequest<RequestType>
{
RequestType GetRequest(BinaryReader stream);
RequestType GetRequest(byte[] requestBytes);
//void WriteTo(Stream stream);
byte[] GetBytes();
}
}

13
Network/IResponse.cs Normal file
View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Network
{
public interface IResponse
{
void WriteTo(BinaryWriter writer);
byte[] GetBytes();
}
}

78
Network/Network.csproj Normal file
View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Network</RootNamespace>
<AssemblyName>Network</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\Network.Rest\rest.snk</AssemblyOriginatorKeyFile>
<TargetFrameworkSubset>
</TargetFrameworkSubset>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BinaryRequest.cs" />
<Compile Include="BinaryResponse.cs" />
<Compile Include="Command.cs" />
<Compile Include="CommandDescriptor.cs" />
<Compile Include="CommandFactory.cs" />
<Compile Include="IRequest.cs" />
<Compile Include="IResponse.cs" />
<Compile Include="RequestEventArgs.cs" />
<Compile Include="Server.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\Network.Rest\rest.snk">
<Link>rest.snk</Link>
</None>
<None Include="app.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Network")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Network")]
[assembly: AssemblyCopyright("Copyright © 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1b8150fa-dc0c-4962-a6a5-1e6ebe19847f")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
namespace Network
{
public class RequestEventArgs : RequestEventArgs<BinaryRequest, BinaryResponse>
{
}
public class RequestEventArgs<RequestType, ResponseType> : EventArgs
where ResponseType : IResponse
{
public RequestEventArgs()
{
//Response = new HttpResponse();
}
public RequestType Request { get; set; }
public ResponseType Response { get; set; }
public virtual IPEndPoint Host { get; set; }
}
}

204
Network/Server.cs Normal file
View File

@ -0,0 +1,204 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Collections;
namespace Network
{
public abstract class Server<TRequest, TResponse> : IServiceProvider
where TResponse : IResponse
where TRequest : IRequest<TRequest>, new()
{
public Server(ushort port)
: this(IPAddress.Any, port)
{
}
public Server(IPAddress address, ushort port)
: this(new IPEndPoint(address, port))
{
}
public Server(IPEndPoint host)
{
Host = host;
}
public IPEndPoint Host { get; protected set; }
protected TcpListener tcp;
protected UdpClient udp;
public bool IsTcp { get; set; }
public bool IsUdp { get; set; }
public bool IsStarted { get; set; }
#region Start
public void StartTcp()
{
tcp = new TcpListener(Host);
tcp.Start();
tcp.BeginAcceptTcpClient(ReceiveTcpRequest, null);
OnStart();
IsStarted = true;
}
public void StartUdp()
{
if (IsStarted)
throw new NotSupportedException("You cannot start the server twice");
if (!IsMulticast(Host.Address))
udp = new UdpClient(Host);
else
{
udp = new UdpClient(Host.Port);
udp.JoinMulticastGroup(Host.Address, 5);
udp.BeginReceive(ReceiveUdpRequest, null);
OnStart();
IsStarted = true;
}
}
#endregion
public event EventHandler Started;
public event EventHandler Stopped;
public event EventHandler<RequestEventArgs<TRequest, TResponse>> RequestReceived;
protected abstract RequestEventArgs<TRequest, TResponse> GetEventArgs(TRequest request);
private void ReceiveTcpRequest(IAsyncResult result)
{
TcpClient tcpClient = tcp.EndAcceptTcpClient(result);
if (IsStarted)
tcp.BeginAcceptTcpClient(ReceiveTcpRequest, null);
RequestEventArgs<TRequest, TResponse> rea = GetEventArgs(new TRequest().GetRequest(new BinaryReader(tcpClient.GetStream())));
rea.Host = (IPEndPoint)tcpClient.Client.RemoteEndPoint;
TreatTcp(rea, tcpClient);
}
protected virtual void TreatTcp(RequestEventArgs<TRequest, TResponse> rea, TcpClient tcpClient)
{
OnRequestReceived(rea);
if (rea.Response != null)
Send(rea.Response, tcpClient);
}
protected virtual void TreatUdp(RequestEventArgs<TRequest, TResponse> rea, IPEndPoint client)
{
OnRequestReceived(rea);
if (rea.Response != null)
Send(rea.Response, client);
}
private void ReceiveUdpRequest(IAsyncResult result)
{
IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0);
byte[] requestBytes;
try
{
requestBytes = udp.EndReceive(result, ref remote);
}
catch (SocketException e)
{
if (e.ErrorCode == (int)SocketError.ConnectionAborted || e.ErrorCode == (int)SocketError.ConnectionReset)
return;
throw e;
}
finally
{
if (IsStarted)
udp.BeginReceive(ReceiveUdpRequest, null);
}
if (requestBytes == null)
return;
RequestEventArgs<TRequest, TResponse> rea = GetEventArgs(new TRequest().GetRequest(requestBytes));
rea.Host = remote;
TreatUdp(rea, remote);
}
protected void Send(TResponse response, TcpClient tcpClient)
{
response.WriteTo(new BinaryWriter(tcpClient.GetStream()));
}
protected void Send(TResponse response, IPEndPoint remote)
{
byte[] responseBytes = response.GetBytes();
udp.Send(responseBytes, responseBytes.Length, remote);
}
public void Stop()
{
if (IsStarted)
{
if (IsTcp)
tcp.Stop();
if (IsUdp)
udp.Close();
OnStop();
IsStarted = false;
}
}
public void Restart()
{
Stop();
if (IsTcp)
StartTcp();
if (IsUdp)
StartUdp();
}
protected virtual void OnStart()
{
if (Started != null)
Started(this, EventArgs.Empty);
}
protected virtual void OnStop()
{
if (Stopped != null)
Stopped(this, EventArgs.Empty);
}
protected virtual void OnRequestReceived(RequestEventArgs<TRequest, TResponse> rea)
{
if (RequestReceived != null)
RequestReceived(this, rea);
}
protected bool IsMulticast(IPAddress hostAddress)
{
if (hostAddress.IsIPv6Multicast)
return true;
byte[] addressBytes = hostAddress.GetAddressBytes();
if (addressBytes[0] >= 224 && addressBytes[0] <= 239)
return true;
return false;
}
protected IDictionary<Type, object> services = new Dictionary<Type, object>();
#region IServiceProvider Members
public object GetService(Type serviceType)
{
return services[serviceType];
}
public T GetService<T>()
{
return (T)GetService(typeof(T));
}
#endregion
}
}

3
Network/app.config Normal file
View File

@ -0,0 +1,3 @@
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>

View File

@ -12,6 +12,10 @@
<AssemblyName>Services.NET</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -52,6 +56,10 @@
<Project>{36528547-53DC-46CD-8C97-1BAE69262B00}</Project>
<Name>Network.Dns</Name>
</ProjectReference>
<ProjectReference Include="..\Network\Network.csproj">
<Project>{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}</Project>
<Name>Network %28Network\Network%29</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -12,6 +12,10 @@
<AssemblyName>UPnP</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -56,10 +60,14 @@
<Project>{36528547-53DC-46CD-8C97-1BAE69262B00}</Project>
<Name>Network.Dns</Name>
</ProjectReference>
<ProjectReference Include="..\Rest\Network.Rest.csproj">
<Project>{3FFE9D8C-3914-4DD1-BB7C-8D4359216806}</Project>
<ProjectReference Include="..\Network.Rest\Network.Rest.csproj">
<Project>{13A68F9C-F095-409E-A97D-A05FFCDCE210}</Project>
<Name>Network.Rest</Name>
</ProjectReference>
<ProjectReference Include="..\Network\Network.csproj">
<Project>{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}</Project>
<Name>Network %28Network\Network%29</Name>
</ProjectReference>
<ProjectReference Include="..\SD\Network.ZeroConf.csproj">
<Project>{2B2D41E0-DBC7-4075-873C-394D02448281}</Project>
<Name>Network.ZeroConf</Name>

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -83,7 +83,7 @@ namespace Network.UPnP
protected void TreatQuery(byte[] bytes)
{
HttpRequest request = HttpRequest.FromBytes(bytes);
HttpRequest request = new HttpRequest().GetRequest(bytes);
if (QueryReceived != null)
QueryReceived(request);
}

View File

@ -12,6 +12,10 @@
<AssemblyName>UPnPReader</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -49,10 +53,14 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Rest\Network.Rest.csproj">
<Project>{3FFE9D8C-3914-4DD1-BB7C-8D4359216806}</Project>
<ProjectReference Include="..\Network.Rest\Network.Rest.csproj">
<Project>{13A68F9C-F095-409E-A97D-A05FFCDCE210}</Project>
<Name>Network.Rest</Name>
</ProjectReference>
<ProjectReference Include="..\Network\Network.csproj">
<Project>{C05DF064-DD81-49AE-91D2-9D8BBCC76F1F}</Project>
<Name>Network %28Network\Network%29</Name>
</ProjectReference>
<ProjectReference Include="..\SD\Network.ZeroConf.csproj">
<Project>{2B2D41E0-DBC7-4075-873C-394D02448281}</Project>
<Name>Network.ZeroConf</Name>

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

View File

@ -12,6 +12,10 @@
<AssemblyName>mDNSReader</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

View File

@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}