@@ -1,45 +1,92 @@
using System.Threading;
using Netronics.Template.Http;
using Netronics.Template.Http.Handler;
using Netronics.Template.Http.SocketIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace WebServer
{
class Program
{
public static readonly AutoResetEvent ExitEvent = new AutoResetEvent(false);

static void Main(string[] args)
{
var handler = new HttpHandler();
handler.AddStatic("^/$", "./www/index.html");
handler.AddStatic("^/script/(.*)$", "./www/script/{1}");
handler.AddStatic("^/file/(.*)$", "./www/test/file/{1}");

handler.AddDynamic("^/test.web$", TestModule.TestController.TestMain);
handler.AddWebSocket("^/echo$", strings => new WebSocketHandler());
handler.AddJSON("^/test.json$", strings =>
{
dynamic json = new JObject();
json.test = "abcd";
json.test2 = 123;
json.a = new JArray(strings);
return json;
});
var io = new SocketIO();
io.On("connection", s =>
{
var socket = s as ISocketIO;
socket.Emit("news", new JArray(JsonConvert.DeserializeObject("{ hello: 'world' }")));
socket.On("my other event", array => System.Console.WriteLine(array[0].my));
});
handler.AddSocketIO(io);

var netronics = new Netronics.Netronics(new HttpProperties(() => handler));
netronics.Start();
ExitEvent.WaitOne();
}
}
}
using System;
using System.Collections.Generic;
using System.Threading;
using Netronics.Template.Http;
using Netronics.Template.Http.Handler;
using Netronics.Template.Http.SocketIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace WebServer
{
class Program
{
public static readonly AutoResetEvent ExitEvent = new AutoResetEvent(false);
private static readonly List<ISocketIO> UserList = new List<ISocketIO>();
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += (s, e) =>
{
};

var handler = new HttpHandler();
handler.AddStatic("^/$", "./www/index.html");
handler.AddStatic("^(.*).css$", "./www/{1}.css");
handler.AddStatic("^/script/(.*)$", "./www/script/{1}");
handler.AddStatic("^/file/(.*)$", "./www/test/file/{1}");

handler.AddDynamic("^/test.web$", TestModule.TestController.TestMain);
handler.AddWebSocket("^/echo$", strings => new WebSocketHandler());
handler.AddJSON("^/test.json$", strings =>
{
dynamic json = new JObject();
json.test = "abcd";
json.test2 = 123;
json.a = new JArray(strings);
return json;
});
var io = new SocketIO();
io.On("connection", s =>
{
var socket = s as ISocketIO;
lock (UserList)
{
UserList.Add(socket);

dynamic obj = new JObject();
obj.name = "System";
obj.msg = socket.ToString() + " 접속";
foreach (var sock in UserList)
{
sock.Emit("chat", new JArray(new object[] { obj }));
}
}

socket.On("chat", o =>
{
dynamic obj = new JObject();
obj.name = socket.ToString();
obj.msg = o[0].msg;
lock (UserList)
{
foreach (var sock in UserList)
{
sock.Emit("chat", new JArray(new object[] { obj }));
}
}
});
});
io.On("disconnect", o =>
{
var socket = o as ISocketIO;
lock (UserList)
{
UserList.Remove(socket);

dynamic obj = new JObject();
obj.name = "System";
obj.msg = socket.ToString() + " 접속 종료";
foreach (var sock in UserList)
{
sock.Emit("chat", new JArray(new object[] { obj }));
}
}
});
handler.AddSocketIO(io);

var netronics = new Netronics.Netronics(new HttpsProperties(() => handler));
netronics.Start();
ExitEvent.WaitOne();
}
}
}
@@ -22,7 +22,7 @@ protected bool ReceivePacket(byte[] buffer, int len)
return true;
}

protected void Disconnected()
protected virtual void Disconnected()
{
lock (_packetBuffer)
{
@@ -73,6 +73,13 @@ public override void Disconnect()
}, null);
}

protected override void Disconnected()
{
base.Disconnected();
_socket.Dispose();
}



public override void SendMessage(dynamic message)
{
@@ -0,0 +1,134 @@
using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Threading;

namespace Netronics.Channel.Channel
{
public class SslChannel : Channel
{
public static SslChannel CreateChannel(Socket socket, System.Security.Cryptography.X509Certificates.X509Certificate certificate)
{
var channel = new SslChannel(socket);
channel._stream.AuthenticateAsServer(certificate);
return channel;
}

public static SslChannel CreateChannel(Socket socket, string host)
{
var channel = new SslChannel(socket);
channel._stream.AuthenticateAsClient(host);
return channel;
}

private readonly byte[] _originalPacketBuffer = new byte[512];
private readonly Socket _socket;
private readonly SslStream _stream;

private object _tag;

private SslChannel(Socket socket)
{
_socket = socket;
_stream = new SslStream(new NetworkStream(socket, true));
}

public Socket GetSocket()
{
return _socket;
}

public override string ToString()
{
return _socket.RemoteEndPoint.ToString();
}

protected override void BeginReceive()
{
try
{
_stream.BeginRead(_originalPacketBuffer, 0, 512, ReadCallback, null);
}
catch (SocketException)
{
Disconnect();
}
}

private void ReadCallback(IAsyncResult ar)
{
int len;
try
{
len = _stream.EndRead(ar);
if (len == 0)
throw new SocketException();
}
catch (SocketException)
{
ThreadPool.QueueUserWorkItem((o) => Disconnect());
return;
}

ReceivePacket(_originalPacketBuffer, len);
}

public override void Disconnect()
{
_socket.BeginDisconnect(false, ar =>
{
if (GetHandler() != null)
GetHandler().Disconnected(this);
Disconnected();
}, null);
}

protected override void Disconnected()
{
base.Disconnected();
_socket.Dispose();
}



public override void SendMessage(dynamic message)
{
PacketBuffer buffer = GetProtocol().GetEncoder().Encode(this, message);

if (buffer == null)
return;
byte[] o = buffer.GetBytes();
buffer.Dispose();

try
{
_stream.BeginWrite(o, 0, o.Length, SendCallback, null);
}
catch (SocketException)
{
}
}

public override object SetTag(object tag)
{
_tag = tag;
return _tag;
}

public override object GetTag()
{
return _tag;
}

private void SendCallback(IAsyncResult ar)
{
try
{
_socket.EndSend(ar);
}
catch (SocketException)
{
}
}
}
}
@@ -6,14 +6,14 @@
namespace Netronics.Channel
{
/// <summary>
/// <see cref="SetProtocol"/>과 <see cref="SetHandler"/>를 사용할 수 있는 <see cref="IChannelFactory"/>
/// <see cref="SetProtocol"/>과 <see cref="SetHandler"/>를 사용할 수 있는 <see cref="IChannelPipe"/>
/// </summary>
public class ChannelFactory : IChannelFactory
public class ChannelPipe : IChannelPipe
{
private Func<IChannelHandler> _handler = () => new ChannelHandler();
private Func<IProtocol> _procotol = () => null;

#region IChannelFactory Members
#region IChannelPipe Members

public IChannel CreateChannel(Netronics netronics, Socket socket)
{
@@ -31,14 +31,14 @@ public IChannel CreateChannel(Netronics netronics, Socket socket)
///
/// <example>
/// <code>
/// ChannelFactory factory = new ChannelFactory();
/// ChannelPipe factory = new ChannelPipe();
/// factory.SetProtocol(()=>new ExampleProtocol());
/// </code>
/// </example>
///
/// <param name="func"><see cref="IChannel"/>에서 사용할 <see cref="IProtocol"/>를 가져오는 Func</param>
/// <returns>자신의 인스턴스</returns>
public ChannelFactory SetProtocol(Func<IProtocol> func)
public ChannelPipe SetProtocol(Func<IProtocol> func)
{
_procotol = func;
return this;
@@ -50,14 +50,14 @@ public ChannelFactory SetProtocol(Func<IProtocol> func)
///
/// <example>
/// <code>
/// ChannelFactory factory = new ChannelFactory();
/// ChannelPipe factory = new ChannelPipe();
/// factory.SetHandler(()=>new ExampleHandler());
/// </code>
/// </example>
///
/// <param name="func"><see cref="IChannel"/>에서 사용할 <see cref="IChannelHandler"/>를 가져오는 Func</param>
/// <returns>자신의 인스턴스</returns>
public ChannelFactory SetHandler(Func<IChannelHandler> func)
public ChannelPipe SetHandler(Func<IChannelHandler> func)
{
_handler = func;
return this;
@@ -5,9 +5,9 @@ namespace Netronics.Channel
{
/// <summary>
/// <see cref="Netronics"/>의 핵심 인터페이스인 <see cref="IChannel"/>의 생성을 담당하는 인터페이스.
/// <see cref="IProperties"/>의 <see cref="IProperties.GetChannelFactory"/>에 의해 <see cref="Netronics"/>로 전달됩니다.
/// <see cref="IProperties"/>의 <see cref="IProperties.GetChannelPipe"/>에 의해 <see cref="Netronics"/>로 전달됩니다.
/// </summary>
public interface IChannelFactory
public interface IChannelPipe
{
/// <summary>
/// 채널을 생성하는 메서드
@@ -18,7 +18,7 @@ protected override void InitSocket()
protected override void StartSocket()
{
Socket.Connect(Properties.GetIPEndPoint());
_channel = AddChannel(Properties.GetChannelFactory().CreateChannel(this, Socket));
_channel = AddChannel(Properties.GetChannelPipe().CreateChannel(this, Socket));
_channel.Connect();
}

@@ -9,6 +9,6 @@ public interface IProperties
void OnStartEvent(Netronics netronics, EventArgs eventArgs);
void OnStopEvent(Netronics netronics, EventArgs eventArgs);
IPEndPoint GetIPEndPoint();
IChannelFactory GetChannelFactory();
IChannelPipe GetChannelPipe();
}
}
@@ -54,7 +54,7 @@ public virtual IPEndPoint GetEndIPPoint()

protected virtual void AcceptCallback(IAsyncResult ar)
{
AddChannel(Properties.GetChannelFactory().CreateChannel(this, Socket.EndAccept(ar))).Connect();
AddChannel(Properties.GetChannelPipe().CreateChannel(this, Socket.EndAccept(ar))).Connect();
Socket.BeginAccept(AcceptCallback, null);
}

@@ -65,7 +65,7 @@ public virtual IChannel AddChannel(IChannel channel)

public virtual IChannel AddSocket(Socket socket)
{
return AddChannel(Properties.GetChannelFactory().CreateChannel(this, socket));
return AddChannel(Properties.GetChannelPipe().CreateChannel(this, socket));
}
}
}
@@ -74,6 +74,7 @@
<Compile Include="Channel\ChannelHandler.cs" />
<Compile Include="Channel\Channel\Channel.cs" />
<Compile Include="Channel\Channel\IChannel.cs" />
<Compile Include="Channel\Channel\SslChannel.cs" />
<Compile Include="Channel\IChannelHandler.cs" />
<Compile Include="Channel\Channel\IKeepHandlerChannel.cs" />
<Compile Include="Channel\Channel\IKeepParallelChannel.cs" />
@@ -100,6 +101,7 @@
<Compile Include="Template\Http\Handler\HttpHandler.cs" />
<Compile Include="Template\Http\HttpProperties.cs" />
<Compile Include="Template\Http\Handler\IUriHandler.cs" />
<Compile Include="Template\Http\HttpsProperties.cs" />
<Compile Include="Template\Http\Module\Controller.cs" />
<Compile Include="Template\Http\Module\Module.cs" />
<Compile Include="Template\Http\SocketIO\ISocketIO.cs" />
@@ -111,9 +113,9 @@
<Compile Include="Template\Http\UriFinder.cs" />
<Compile Include="Protocol\PacketEncoder\Bson\BsonDecoder.cs" />
<Compile Include="Protocol\PacketEncoder\Bson\BsonEncoder.cs" />
<Compile Include="Channel\ChannelFactory.cs" />
<Compile Include="Channel\ChannelPipe.cs" />
<Compile Include="Channel\Channel\SocketChannel.cs" />
<Compile Include="Channel\IChannelFactory.cs" />
<Compile Include="Channel\IChannelPipe.cs" />
<Compile Include="Properties.cs" />
<Compile Include="Netronics.cs" />
<Compile Include="PacketBuffer.cs" />
@@ -6,17 +6,17 @@ namespace Netronics
{
public class Properties : IProperties
{
protected IChannelFactory ChannelFactory = new ChannelFactory();
protected IChannelPipe ChannelPipe = new ChannelPipe();
protected IPEndPoint IpEndPoint = new IPEndPoint(IPAddress.Any, 0);

protected event EventHandler StartEvent;
protected event EventHandler StopEvent;

public static Properties CreateProperties(IPEndPoint ipEndPoint, ChannelFactory factory)
public static Properties CreateProperties(IPEndPoint ipEndPoint, ChannelPipe pipe)
{
var properties = new Properties();
properties.SetIpEndPoint(ipEndPoint);
properties.ChannelFactory = factory;
properties.ChannelPipe = pipe;
return properties;
}

@@ -38,9 +38,9 @@ public Properties SetIpEndPoint(IPEndPoint endPoint)
return this;
}

public Properties SetChannelFactoryOption(Action<IChannelFactory> action)
public Properties SetChannelFactoryOption(Action<IChannelPipe> action)
{
action(GetChannelFactory());
action(GetChannelPipe());
return this;
}

@@ -49,9 +49,9 @@ public IPEndPoint GetIPEndPoint()
return IpEndPoint;
}

public IChannelFactory GetChannelFactory()
public IChannelPipe GetChannelPipe()
{
return ChannelFactory;
return ChannelPipe;
}
}
}
@@ -17,7 +17,7 @@
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하십시오.
[assembly: ComVisible(false)]
[assembly: ComVisible(true)]

// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("f69cf68c-23fa-4699-a921-8c7bc56276e3")]
@@ -29,5 +29,5 @@
// 상태 번호
// 빌드 번호
//
[assembly: AssemblyVersion("0.1.1.68")]
[assembly: AssemblyFileVersion("0.1.1.68")]
[assembly: AssemblyVersion("0.1.2.85")]
[assembly: AssemblyFileVersion("0.1.2.85")]
@@ -16,7 +16,7 @@ public class HttpProperties : Properties, IProtocol
public HttpProperties(Func<IChannelHandler> handler, int port = 80)
{
IpEndPoint = new IPEndPoint(IPAddress.Any, port);
((ChannelFactory) ChannelFactory).SetProtocol(()=>this).SetHandler(handler);
((ChannelPipe) ChannelPipe).SetProtocol(()=>this).SetHandler(handler);
}

public IPacketEncryptor GetEncryptor()
@@ -0,0 +1,75 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using Netronics.Channel;
using Netronics.Channel.Channel;
using Netronics.Protocol;
using Netronics.Protocol.PacketEncoder;
using Netronics.Protocol.PacketEncoder.Http;
using Netronics.Protocol.PacketEncryptor;

namespace Netronics.Template.Http
{
public class HttpsProperties : IProperties, IProtocol, IChannelPipe
{
private static readonly HttpEncoder Encoder = new HttpEncoder();
private static readonly HttpDecoder Decoder = new HttpDecoder();
private readonly Func<IChannelHandler> _handler;
protected IPEndPoint IpEndPoint = new IPEndPoint(IPAddress.Any, 0);


public HttpsProperties(Func<IChannelHandler> handler, int port = 443)
{
IpEndPoint = new IPEndPoint(IPAddress.Any, port);
_handler = handler;
}

public IChannel CreateChannel(Netronics netronics, Socket socket)
{
SslChannel channel = SslChannel.CreateChannel(socket, X509Certificate.CreateFromCertFile("test.cert"));
channel.SetProtocol(this);
channel.SetHandler(_handler());
return channel;
}

public IPacketEncryptor GetEncryptor()
{
return null;
}

public IPacketDecryptor GetDecryptor()
{
return null;
}

public IPacketEncoder GetEncoder()
{
return Encoder;
}

public IPacketDecoder GetDecoder()
{
return Decoder;
}


public void OnStartEvent(Netronics netronics, EventArgs eventArgs)
{
}

public void OnStopEvent(Netronics netronics, EventArgs eventArgs)
{
}

public IPEndPoint GetIPEndPoint()
{
return IpEndPoint;
}

public IChannelPipe GetChannelPipe()
{
return this;
}
}
}
@@ -32,6 +32,11 @@ public IChannel GetChannel()
return _channel;
}

public override string ToString()
{
return _channel.ToString();
}

public void Connected(IChannel channel)
{
if (channel.ToString().Substring(0, channel.ToString().IndexOf(":", StringComparison.Ordinal))
@@ -61,7 +66,8 @@ public void Disconnected(IChannel channel)
if(channel != _channel)
return;

_heartbeatTimer.Dispose();
if (_heartbeatTimer != null)
_heartbeatTimer.Dispose();
_heartbeatTimer = null;

Send("0", "");
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace Service.Coroutine
{
class Co
{
[ThreadStatic]
public static Coroutine Current;

// 중간에서 yield할 수 있는 로직은 반드시 yield return Co.Call 형태를 사용해야 한다.
public static IYield Call(IEnumerator<IYield> e)
{
return new NestedYield(e);
}

// k초 뒤에 현재 코루틴을 재개하도록 스케줄링
// 이런 식으로 IO 함수도 만들 수 있다.
// IO가 완료되면 실행하도록 콜백을 등록하게 하면 됨

/*
public static IEnumerator<IYield> Sleep(int t)
{
Coroutine c = Current;
/*Debug.Assert(c != null);
// 스케줄러 복잡하게 짜기 귀찮으니 대충 Sleep했다고 치고 실행 큐 마지막에 등록
Scheduler.Schedule(
delegate() { c.Resume(); },
t);///
yield return new NonNestedYield();
}
*/
}

}
@@ -0,0 +1,26 @@
using System.Collections.Generic;

namespace Service.Coroutine
{
class Coroutine
{
public delegate IEnumerator<IYield> CoroutineEntrance();

public Coroutine(CoroutineEntrance entrance)
{
Co.Current = this;
y = Co.Call(entrance());
Co.Current = null;
}

public bool Resume()
{
Co.Current = this;
bool ret = y.Resume();
Co.Current = null;
return ret;
}

private IYield y;
}
}
@@ -0,0 +1,7 @@
namespace Service.Coroutine
{
public interface IYield
{
bool Resume();
}
}
@@ -0,0 +1,31 @@
using System.Collections.Generic;

namespace Service.Coroutine
{
class NestedYield : IYield
{
public NestedYield(IEnumerator<IYield> e)
{
_e = e;
_valid = e.MoveNext();
}

public bool Resume()
{
if (!_valid)
{
return false;
}
if (_e.Current.Resume())
{
return true;
}
_valid = _e.MoveNext();
return _valid;
}

private readonly IEnumerator<IYield> _e;
private bool _valid;

}
}
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Service.Coroutine
{
class NonNestedYield : IYield
{
public bool Resume()
{
return false;
}
}

}
@@ -0,0 +1,23 @@
using Netronics.Channel;
using Netronics.Channel.Channel;

namespace Service.Manager
{
class Handler : IChannelHandler
{
public void Connected(IChannel channel)
{
}

public void Disconnected(IChannel channel)
{
}

public void MessageReceive(IChannel channel, dynamic message)
{
if(message.type == "")
{
}
}
}
}
@@ -0,0 +1,43 @@
using Netronics;
using Netronics.Channel.Channel;
using Netronics.Protocol.PacketEncoder;
using Service.Manager.Packets;

namespace Service.Manager
{
class PacketEncoder : IPacketEncoder, IPacketDecoder
{
public PacketBuffer Encode(IChannel channel, dynamic data)
{
if(data is Ping)
{
var packet = new PacketBuffer();
packet.WriteByte(0);
return packet;
}

if(data is JoinService)
{
var packet = new PacketBuffer();
packet.WriteByte(1);
return packet;
}
return null;
}

public dynamic Decode(IChannel channel, PacketBuffer buffer)
{
buffer.BeginBufferIndex();
if (buffer.AvailableBytes() < 1)
return null;

byte type = buffer.ReadByte();
if(type == 0)
{
buffer.EndBufferIndex();
return new Ping();
}
return null;
}
}
}
@@ -0,0 +1,9 @@
using System.Collections.Generic;

namespace Service.Manager.Packets
{
class JoinService
{
public string Name;
}
}
@@ -0,0 +1,6 @@
namespace Service.Manager.Packets
{
class Ping
{
}
}
@@ -0,0 +1,81 @@
using System;
using System.Net;
using System.Net.Sockets;
using Netronics;
using Netronics.Channel;
using Netronics.Channel.Channel;
using Netronics.Protocol;
using Netronics.Protocol.PacketEncoder;
using Netronics.Protocol.PacketEncoder.Bson;
using Netronics.Protocol.PacketEncryptor;
using Netronics.Template.Http.Handler;

namespace Service.Manager
{
class ServiceManager : IProperties, IChannelPipe, IProtocol
{
private static ServiceManager _manager;

private static readonly BsonEncoder Encoder = new BsonEncoder();
private static readonly BsonDecoder Decoder = new BsonDecoder();

private readonly Netronics.Netronics _netronics;

public static void Load(string name)
{
_manager = new ServiceManager();
}

public ServiceManager()
{
_netronics = new Netronics.Netronics(this);
_netronics.Start();
}

public void OnStartEvent(Netronics.Netronics netronics, EventArgs eventArgs)
{
}

public void OnStopEvent(Netronics.Netronics netronics, EventArgs eventArgs)
{
}

public IPEndPoint GetIPEndPoint()
{
return new IPEndPoint(IPAddress.Any, 1005);
}

public IChannelPipe GetChannelPipe()
{
return this;
}

public IChannel CreateChannel(Netronics.Netronics netronics, Socket socket)
{
var channel = SocketChannel.CreateChannel(socket);
channel.SetProtocol(this);
channel.SetHandler(new Handler());
return channel;
}

public IPacketEncryptor GetEncryptor()
{
return null;
}

public IPacketDecryptor GetDecryptor()
{
return null;
}

public IPacketEncoder GetEncoder()
{
return Encoder;
}

public IPacketDecoder GetDecoder()
{
return Decoder;
}
}
}
@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Service.Service.Loader;

namespace Service
{
class Program
{
public static readonly AutoResetEvent ExitEvent = new AutoResetEvent(false);

static void ServiceLoad(string servicesFilePath)
{
if (!File.Exists(servicesFilePath))
throw new Exception("system.ns 파일이 존재하지 않습니다.");

var servicesDirectory = new FileInfo(servicesFilePath).DirectoryName;
var serviceList = new List<string>();
foreach (var line in File.ReadLines(servicesFilePath))
{
if (serviceList.Exists((str) => str == line.ToLower()))
throw new Exception("system.ns에 중복된 서비스 이름이 존재합니다.");

serviceList.Add(line.ToLower());
if (line.ToLower() == "servicemanager")
{
Manager.ServiceManager.Load(servicesDirectory);
continue;
}

if (!File.Exists(servicesDirectory + "/" + line))
throw new Exception(line + " 서비스를 찾을 수 없습니다.");


ServiceLoader.Load(servicesDirectory, line);
}
}

static void Main(string[] args)
{
//차후 명령처리를 위해서...

var servicesFilePath = AppDomain.CurrentDomain.BaseDirectory + "system.ns";
if (args.Length > 0)
servicesFilePath = args[args.Length - 1];

//테스트
servicesFilePath = @"C:\Users\Sanghyuck\Projects\Parfe Server\bin\system.ns";

ServiceLoad(servicesFilePath);

/*
string host_name = Dns.GetHostName();
IPHostEntry ips = Dns.GetHostEntry(host_name);
foreach (IPAddress ip in ips.AddressList)
{
Console.Write(ip.ToString());
}*/


ExitEvent.WaitOne();
}
}
}
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// 어셈블리의 일반 정보는 다음 특성 집합을 통해 제어됩니다.
// 어셈블리와 관련된 정보를 수정하려면
// 이 특성 값을 변경하십시오.
[assembly: AssemblyTitle("Service")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Service")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하십시오.
[assembly: ComVisible(false)]

// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("388e6913-4149-4658-92a6-e73f47211ed3")]

// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 버전이 자동으로
// 지정되도록 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{4CA1EF2C-573E-4885-B167-56AD75F6B5F1}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Service</RootNamespace>
<AssemblyName>Service</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\bin\Release\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Manager\Handler.cs" />
<Compile Include="Manager\PacketEncoder.cs" />
<Compile Include="Manager\Packets\JoinService.cs" />
<Compile Include="Manager\Packets\Ping.cs" />
<Compile Include="Manager\ServiceManager.cs" />
<Compile Include="Service\Command.cs" />
<Compile Include="Coroutine\Co.cs" />
<Compile Include="Coroutine\Coroutine.cs" />
<Compile Include="Coroutine\IYield.cs" />
<Compile Include="Coroutine\NestedYield.cs" />
<Compile Include="Coroutine\NonNestedYield.cs" />
<Compile Include="Service\Entity.cs" />
<Compile Include="Service\IServiceInfo.cs" />
<Compile Include="Service\Loader\ManagerProcessor.cs" />
<Compile Include="Service\LocalService.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Service\Service.cs" />
<Compile Include="Service\Loader\ServiceLoader.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Framework\Netronics.csproj">
<Project>{394898C7-12EE-478A-AD9A-7377B5DCC081}</Project>
<Name>Netronics</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<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>
@@ -0,0 +1,9 @@
using System;

namespace Service.Service
{
[AttributeUsage(AttributeTargets.Method)]
public class Command : Attribute
{
}
}
@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Service.Coroutine;

namespace Service.Service
{
public class Entity
{
private static readonly ThreadLocal<Stack<Entity>> Stack = new ThreadLocal<Stack<Entity>>(() => new Stack<Entity>());

private readonly LocalService _service;
private readonly string _uid;

public static Entity CreateEntity(LocalService service, string uid)
{
return new Entity(service, uid);
}

public Entity(LocalService service, string uid)
{
_service = service;
_uid = uid;
}

public LocalService GetLocalService()
{
return _service;
}

public static Entity GetEntity()
{
try
{
return Stack.Value.Peek();
}
catch (InvalidOperationException)
{
return null;
}
}

public IYield Call<T>(Func<T, IEnumerator<IYield>> func) where T : class
{
var t = _service as T;
if(t == null)
throw new Exception("등록된 서비스가 Call 대상을 상속하고 있지 않습니다.");
Stack.Value.Push(this);
var o = new NestedYield(func(t)); //내부에서 패킷 전송후 yield return new NonNestedYield();
Stack.Value.Pop();
return o;
}

public IEnumerator<IYield> Call<T>(Action<T> func)
{
return null;/*
Call<T>(o =>
{
func(o);
return null;
});*/
}
}
}
@@ -0,0 +1,8 @@
namespace Service.Service
{
public interface IServiceInfo
{
string GetServiceName();
LocalService GetService();
}
}
@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using Netronics;
using Netronics.Channel;
using Netronics.Channel.Channel;
using Netronics.Protocol;
using Netronics.Protocol.PacketEncoder;
using Netronics.Protocol.PacketEncryptor;

namespace Service.Service.Loader
{
class ManagerProcessor : IProperties, IChannelPipe, IProtocol
{
private readonly Netronics.Netronics _manager;
private ServiceLoader _loader;

private readonly string[] _host;
private IPEndPoint _managerIPEndPoint;

public ManagerProcessor(ServiceLoader loader, string[] host)
{
_loader = loader;
_host = host;
_manager = new Client(this);
var address = GetIPAddress();

Connect();
_manager.Start();
}

private List<IPAddress> GetIPAddress()
{
var addresses = new List<IPAddress>();

var adapters = NetworkInterface.GetAllNetworkInterfaces();
foreach (var adapter in adapters)
{
var properties = adapter.GetIPProperties();
foreach (var uniCast in properties.UnicastAddresses)
{
if (!IPAddress.IsLoopback(uniCast.Address))
addresses.Add(uniCast.Address);
}
}
return addresses;
}

private bool Connect()
{
var host = GetHost();
if (host == null)
return false;
_managerIPEndPoint = new IPEndPoint(IPAddress.Parse(host), 1005);
return true;
}

private string GetHost()
{
foreach (var host in _host)
{
try
{
var clnt = new TcpClient(host, 1005);
clnt.Close();
return host;
}
catch
{
}
}
return null;
}

public IPEndPoint GetIPEndPoint()
{
return _managerIPEndPoint;
}

public IChannelPipe GetChannelPipe()
{
return this;
}

public void OnStartEvent(Netronics.Netronics netronics, EventArgs eventArgs)
{
}

public void OnStopEvent(Netronics.Netronics netronics, EventArgs eventArgs)
{
}

public IChannel CreateChannel(Netronics.Netronics netronics, Socket socket)
{
return null;
}

public IPacketEncryptor GetEncryptor()
{
return null;
}

public IPacketDecryptor GetDecryptor()
{
return null;
}

public IPacketEncoder GetEncoder()
{
return null;
}

public IPacketDecoder GetDecoder()
{
return null;
}
}
}
@@ -0,0 +1,33 @@
using System;
using System.IO;
using System.Reflection;

namespace Service.Service.Loader
{
class ServiceLoader
{
private IServiceInfo _info;
private ManagerProcessor _manager;

private LocalService _service;

public static void Load(string path, string name)
{
new ServiceLoader(path, name);
}

private ServiceLoader(string path, string name)
{
Assembly asm = Assembly.LoadFrom(path + "/" + name);
var info = asm.GetType(asm.FullName.Substring(0, asm.FullName.IndexOf(",")) + ".ServiceInfo");
if(info == null || !typeof(IServiceInfo).IsAssignableFrom(info))
throw new Exception(asm.FullName.Substring(0, asm.FullName.IndexOf(",")) + ".ServiceInfo가 존재하지 않거나 IServiceInfo를 상속받지 않습니다.");


_info = (IServiceInfo)Activator.CreateInstance(info);
_service = _info.GetService();

_manager = new ManagerProcessor(this, File.ReadAllLines(path + "/manager.ns"));
}
}
}
@@ -0,0 +1,17 @@
namespace Service.Service
{
public class LocalService : Service
{
public virtual void Start()
{
}

public virtual void Stop()
{
}

public virtual void MessageReceive(Service service, object o)
{
}
}
}
@@ -0,0 +1,36 @@
using System.Collections.Generic;

namespace Service.Service
{
public class Service
{
public static LocalService GetService()
{
return Entity.GetEntity().GetLocalService();
}

public virtual Entity NewEntity()
{
if (Entity.GetEntity() == null)
return null;

var localService = Entity.GetEntity().GetLocalService();
if (localService == this)
return null;

var entity = localService.NewEntity();
//entity.AddReceiver(this);
return entity;
}

public Service GetService(string name)
{
return null;
}
public List<Netronics.Template.Service.Service.Service> GetServices(string name)
{
//test
return null;// new RemoteService();
}
}
}
@@ -0,0 +1,3 @@
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>