WIP
parent
dd1cbcfb86
commit
5355940395
11
Program.cs
11
Program.cs
|
@ -20,6 +20,7 @@ using ln.http;
|
|||
using ln.http.resources;
|
||||
using skyspot.http;
|
||||
using skyspot.session;
|
||||
using skyspot.hotspot;
|
||||
|
||||
namespace skyspot
|
||||
{
|
||||
|
@ -29,16 +30,18 @@ namespace skyspot
|
|||
{
|
||||
HTTPServer httpServer = new HTTPServer();
|
||||
httpServer.AddEndpoint(new IPEndPoint(IPAddress.Any, 80));
|
||||
httpServer.Start();
|
||||
|
||||
HotspotManager hotspotManager = new HotspotManager();
|
||||
|
||||
|
||||
|
||||
|
||||
ResourceApplication app = new SkySpotApplication();
|
||||
httpServer.DefaultApplication = app;
|
||||
|
||||
//DHCP httpDHCP = new DHCP(null,dhcpServer);
|
||||
//(app.RootResource as DirectoryResource).InjectResource(httpDHCP);
|
||||
|
||||
SessionManager sessionManager = new SessionManager();
|
||||
|
||||
httpServer.Start();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
|
||||
Radius Secret Lookup:
|
||||
---------------------
|
||||
|
||||
1. SecretStore individual secret
|
||||
2. HotSpot Default Secret
|
||||
3. SecretStore default secret
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
namespace skyspot.hotspot
|
||||
{
|
||||
public class ClientProfile
|
||||
{
|
||||
public String Name { get; set; }
|
||||
|
||||
public ClientProfile()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using skyspot.radius;
|
||||
using System.Linq;
|
||||
using skyspot.session;
|
||||
namespace skyspot.hotspot
|
||||
{
|
||||
public class HotspotManager
|
||||
|
@ -28,7 +29,12 @@ namespace skyspot.hotspot
|
|||
public ODBCollection<HotspotNetwork> hotspotNetworks { get; private set; }
|
||||
public ODBCollection<RadiusSecretsStore> radiusSecretsCollection;
|
||||
|
||||
Dictionary<HotspotNetwork, HotspotRuntime> instances = new Dictionary<HotspotNetwork, HotspotRuntime>();
|
||||
|
||||
|
||||
|
||||
MappingBTree<HotspotNetwork, HotspotNetworkRuntime> hotspotRuntimes = new MappingBTree<HotspotNetwork, HotspotNetworkRuntime>((hr) => hr.HotspotNetwork);
|
||||
|
||||
public SessionManager SessionManager { get; private set; }
|
||||
|
||||
public HotspotManager()
|
||||
{
|
||||
|
@ -39,17 +45,49 @@ namespace skyspot.hotspot
|
|||
SecretsStore = radiusSecretsCollection.FirstOrDefault();
|
||||
if (SecretsStore == null)
|
||||
SecretsStore = new RadiusSecretsStore();
|
||||
|
||||
SessionManager = new SessionManager(this);
|
||||
}
|
||||
|
||||
public void SaveSecretsStore() => radiusSecretsCollection.Upsert(SecretsStore);
|
||||
|
||||
|
||||
|
||||
class HotspotRuntime
|
||||
public void AddHotspotNetwork(HotspotNetwork hotspotNetwork)
|
||||
{
|
||||
public BTree<MAC, HotspotSession> currentSessions { get; } = new BTree<MAC, HotspotSession>();
|
||||
|
||||
if (!hotspotRuntimes.ContainsKey(hotspotNetwork))
|
||||
hotspotRuntimes.Add(new HotspotNetworkRuntime(hotspotNetwork));
|
||||
}
|
||||
public void RemoveHotspotNetwork(HotspotNetwork hotspotNetwork)
|
||||
{
|
||||
if (hotspotRuntimes.ContainsKey(hotspotNetwork))
|
||||
{
|
||||
hotspotRuntimes.RemoveKey(hotspotNetwork);
|
||||
}
|
||||
}
|
||||
public HotspotNetworkRuntime GetHotspotNetworkRuntime(HotspotNetwork hotspotNetwork)
|
||||
{
|
||||
return hotspotRuntimes[hotspotNetwork];
|
||||
}
|
||||
public HotspotNetworkRuntime GetHotspotNetworkRuntime(string networkName)
|
||||
{
|
||||
foreach (HotspotNetworkRuntime hotspotNetworkRuntime in hotspotRuntimes)
|
||||
{
|
||||
if (hotspotNetworkRuntime.HotspotNetwork.Name.Equals(networkName))
|
||||
return hotspotNetworkRuntime;
|
||||
}
|
||||
throw new KeyNotFoundException();
|
||||
}
|
||||
|
||||
public HotspotNetwork GetHotspotNetwork(String name)
|
||||
{
|
||||
foreach (HotspotNetworkRuntime hotspotNetworkRuntime in hotspotRuntimes)
|
||||
{
|
||||
if (hotspotNetworkRuntime.HotspotNetwork.Name.Equals(name))
|
||||
return hotspotNetworkRuntime.HotspotNetwork;
|
||||
}
|
||||
throw new KeyNotFoundException();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
using System;
|
||||
using ln.types.odb.attributes;
|
||||
using ln.types.net;
|
||||
using System.Text;
|
||||
namespace skyspot.hotspot
|
||||
{
|
||||
public class HotspotNetwork
|
||||
public class HotspotNetwork : IComparable
|
||||
{
|
||||
[DocumentID]
|
||||
public readonly Guid ID = Guid.NewGuid();
|
||||
|
@ -23,10 +24,31 @@ namespace skyspot.hotspot
|
|||
public string SID { get; set; }
|
||||
|
||||
public Network4 ClientsNetwork { get; set; }
|
||||
public IPv4 Gateway { get; set; }
|
||||
|
||||
public byte[] RadiusSecret { get; set; }
|
||||
public string RadiusTextSecret
|
||||
{
|
||||
get => Encoding.UTF8.GetString(RadiusSecret);
|
||||
set => RadiusSecret = Encoding.UTF8.GetBytes(value);
|
||||
}
|
||||
|
||||
public TimeSpan ClientDefaultSessionTime { get; set; }
|
||||
public ClientProfile DefaultClientProfile { get; set; }
|
||||
|
||||
|
||||
public HotspotNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
if (obj is HotspotNetwork)
|
||||
{
|
||||
HotspotNetwork you = obj as HotspotNetwork;
|
||||
return string.Compare(Name, you.Name, StringComparison.Ordinal);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using ln.types.btree;
|
||||
using ln.types.net;
|
||||
using skyspot.session;
|
||||
using skyspot.ip;
|
||||
namespace skyspot.hotspot
|
||||
{
|
||||
public class HotspotNetworkRuntime
|
||||
{
|
||||
public HotspotNetwork HotspotNetwork { get; private set; }
|
||||
|
||||
MappingBTree<MAC, ClientSession> currentSessions = new MappingBTree<MAC, ClientSession>((ClientSession clientSession)=>clientSession.ClientMAC);
|
||||
IPPool<ClientSession> pool = new IPPool<ClientSession>();
|
||||
|
||||
|
||||
private HotspotNetworkRuntime()
|
||||
{
|
||||
}
|
||||
public HotspotNetworkRuntime(HotspotNetwork hotspotNetwork)
|
||||
{
|
||||
HotspotNetwork = hotspotNetwork;
|
||||
}
|
||||
|
||||
public ClientSession GetSession(MAC clientMac)
|
||||
{
|
||||
if (!currentSessions.ContainsKey(clientMac))
|
||||
{
|
||||
ClientSession newSession = new ClientSession(HotspotNetwork, clientMac);
|
||||
FixupSession(newSession);
|
||||
currentSessions.Add(newSession);
|
||||
return newSession;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClientSession clientSession = currentSessions[clientMac];
|
||||
FixupSession(clientSession);
|
||||
return clientSession; ;
|
||||
}
|
||||
}
|
||||
public void RemoveSession(MAC clientMac)
|
||||
{
|
||||
currentSessions.RemoveKey(clientMac);
|
||||
}
|
||||
|
||||
private void FixupSession(ClientSession clientSession)
|
||||
{
|
||||
if (clientSession.ClientIP == null)
|
||||
{
|
||||
// Todo: Implement IP allocation from pool
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
namespace skyspot.hotspot
|
||||
{
|
||||
public class HotspotUser
|
||||
{
|
||||
public HotspotUser()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
using System;
|
||||
using ln.types.btree;
|
||||
using ln.types.net;
|
||||
namespace skyspot.ip
|
||||
{
|
||||
public class IPPool<T> where T : IComparable
|
||||
{
|
||||
public IPv4 FirstIP { get; set; }
|
||||
public IPv4 LastIP { get; set; }
|
||||
|
||||
public IPv4 NextIP { get; set;}
|
||||
|
||||
BTree<IPv4, T> forward = new BTree<IPv4, T>();
|
||||
BTree<T, IPv4> reverse = new BTree<T, IPv4>();
|
||||
|
||||
public IPPool()
|
||||
{
|
||||
}
|
||||
|
||||
public T FindForward(IPv4 ip)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
return forward[ip];
|
||||
}
|
||||
}
|
||||
public IPv4 FindReverse(T lookup)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
return reverse[lookup];
|
||||
}
|
||||
}
|
||||
|
||||
public void Assign(IPv4 ip, T assigned)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (forward.ContainsKey(ip) || reverse.ContainsKey(assigned))
|
||||
throw new ArgumentException("<ip> or <assigend> already in pool");
|
||||
forward.Add(ip, assigned);
|
||||
reverse.Add(assigned, ip);
|
||||
}
|
||||
}
|
||||
public void Remove(IPv4 ip)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (forward.ContainsKey(ip))
|
||||
{
|
||||
reverse.Remove(forward[ip]);
|
||||
forward.Remove(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void RemoveAssigned(T assigned)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (reverse.ContainsKey(assigned))
|
||||
{
|
||||
forward.Remove(reverse[assigned]);
|
||||
reverse.Remove(assigned);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IPv4 Allocate(T assigned)
|
||||
{
|
||||
if (reverse.ContainsKey(assigned))
|
||||
return reverse[assigned];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using skyspot.hotspot;
|
||||
using ln.types.net;
|
||||
using ln.types.odb.attributes;
|
||||
namespace skyspot.session
|
||||
{
|
||||
public class ClientSession : IComparable
|
||||
{
|
||||
[DocumentID]
|
||||
Guid id = Guid.NewGuid();
|
||||
|
||||
public DateTimeOffset Created { get; }
|
||||
public DateTimeOffset ValidThrough { get; set; }
|
||||
|
||||
public HotspotNetwork HotspotNetwork { get; }
|
||||
|
||||
public MAC ClientMAC { get; }
|
||||
public IPv4 ClientIP { get; set; }
|
||||
|
||||
public HotspotUser HotspotUser { get; set; }
|
||||
public ClientProfile CurrentProfile { get; set; }
|
||||
|
||||
private ClientSession()
|
||||
{
|
||||
Created = DateTimeOffset.Now;
|
||||
ValidThrough = Created + TimeSpan.FromMinutes(3);
|
||||
}
|
||||
|
||||
public ClientSession(HotspotNetwork hotspotNetwork,MAC clientMac)
|
||||
:this()
|
||||
{
|
||||
HotspotNetwork = hotspotNetwork;
|
||||
ClientMAC = clientMac;
|
||||
}
|
||||
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
if (obj is ClientSession)
|
||||
{
|
||||
ClientSession you = obj as ClientSession;
|
||||
return ClientMAC.CompareTo(you.ClientMAC);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,17 +17,22 @@ using ln.logging;
|
|||
using ln.types.odb;
|
||||
using ln.types.odb.mapped;
|
||||
using skyspot.radius;
|
||||
using System.Text;
|
||||
using skyspot.hotspot;
|
||||
namespace skyspot.session
|
||||
{
|
||||
public class SessionManager
|
||||
{
|
||||
public RadiusSecretsStore SecretsStore { get; private set; }
|
||||
public HotspotManager HotspotManager { get; }
|
||||
public RadiusSecretsStore SecretsStore => HotspotManager.SecretsStore;
|
||||
|
||||
|
||||
RadiusServer accountingRadius;
|
||||
RadiusServer locatorRadius;
|
||||
|
||||
public SessionManager()
|
||||
public SessionManager(HotspotManager hotspotManager)
|
||||
{
|
||||
HotspotManager = hotspotManager;
|
||||
InitializeRadius();
|
||||
}
|
||||
|
||||
|
@ -48,6 +53,9 @@ namespace skyspot.session
|
|||
accountingRadius.MessageReceived = AccountingMessageReceived;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Locator Service
|
||||
*
|
||||
|
@ -97,18 +105,23 @@ namespace skyspot.session
|
|||
}
|
||||
|
||||
MAC clientMac = new MAC(userName.AsText);
|
||||
String instanceName = calledStationID.AsText;
|
||||
String networkName = calledStationID.AsText;
|
||||
|
||||
HotspotNetworkRuntime hotspotNetworkRuntime = HotspotManager.GetHotspotNetworkRuntime(networkName);
|
||||
ClientSession clientSession = hotspotNetworkRuntime.GetSession(clientMac);
|
||||
|
||||
Logging.Log(LogLevel.INFO, "Accounting: Session start for client {0} on Network {1}",clientMac, instanceName);
|
||||
if (clientSession.CurrentProfile == null)
|
||||
clientSession.CurrentProfile = hotspotNetworkRuntime.HotspotNetwork.DefaultClientProfile;
|
||||
|
||||
RadiusMessage reply = new RadiusMessage(radiusMessage.EndPoint, RadiusCode.AccessAccept);
|
||||
reply.Identifier = radiusMessage.Identifier;
|
||||
Logging.Log(LogLevel.INFO, "Accounting: Session start for client {0} on Network {1}",clientMac, networkName);
|
||||
|
||||
RadiusMessage reply = radiusMessage.ConstructReply(RadiusCode.AccessAccept);
|
||||
reply.AddAttribute(new RadiusAttribute.FramedIPAddress().SetIP(IPv4.Parse("10.123.0.4")));
|
||||
if (clientSession.CurrentProfile != null)
|
||||
reply.AddAttribute(new RadiusAttribute.FilterID().SetText(clientSession.CurrentProfile.Name));
|
||||
|
||||
reply.Authenticate(SecretsStore.LookupSecret(reply.EndPoint));
|
||||
radiusServer.Send(reply);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,11 @@
|
|||
<Compile Include="hotspot\HotspotManager.cs" />
|
||||
<Compile Include="hotspot\locator\MACLocation.cs" />
|
||||
<Compile Include="radius\RadiusSecretsStore.cs" />
|
||||
<Compile Include="session\ClientSession.cs" />
|
||||
<Compile Include="hotspot\HotspotUser.cs" />
|
||||
<Compile Include="hotspot\ClientProfile.cs" />
|
||||
<Compile Include="ip\IPPool.cs" />
|
||||
<Compile Include="hotspot\HotspotNetworkRuntime.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ln.http\ln.http.csproj">
|
||||
|
@ -89,6 +94,8 @@
|
|||
<Folder Include="hotspot\" />
|
||||
<Folder Include="hotspot\locator\" />
|
||||
<Folder Include="radius\" />
|
||||
<Folder Include="doc\" />
|
||||
<Folder Include="ip\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
@ -201,6 +208,7 @@
|
|||
<None Include="www\js\sky.controls.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="doc\radius.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
Loading…
Reference in New Issue