diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..45e39ea6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+shadowsocks-csharp
+
+Copyright (c) 2013 clowwindy
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+
diff --git a/shadowsocks-csharp/Encryptor.cs b/shadowsocks-csharp/Encryptor.cs
index 903461f4..ddce03c3 100755
--- a/shadowsocks-csharp/Encryptor.cs
+++ b/shadowsocks-csharp/Encryptor.cs
@@ -75,16 +75,16 @@ namespace shadowsocks_csharp
}
}
- public void Encrypt(byte[] buf)
+ public void Encrypt(byte[] buf, int length)
{
- for (int i = 0; i < buf.Length; i++)
+ for (int i = 0; i < length; i++)
{
buf[i] = encryptTable[buf[i]];
}
}
- public void Decrypt(byte[] buf)
+ public void Decrypt(byte[] buf, int length)
{
- for (int i = 0; i < buf.Length; i++)
+ for (int i = 0; i < length; i++)
{
buf[i] = decryptTable[buf[i]];
}
diff --git a/shadowsocks-csharp/Local.cs b/shadowsocks-csharp/Local.cs
index 9046b57d..14dd7eab 100755
--- a/shadowsocks-csharp/Local.cs
+++ b/shadowsocks-csharp/Local.cs
@@ -2,10 +2,288 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Net.Sockets;
+using System.Net;
+using System.Threading;
namespace shadowsocks_csharp
{
+
+
class Local
{
+ private int port;
+ private Encryptor encryptor;
+ public Local(int port)
+ {
+ this.port = port;
+ this.encryptor = new Encryptor("barfoo!");
+ }
+
+ public void Start()
+ {
+
+ // Create a TCP/IP socket.
+ Socket listener = new Socket(AddressFamily.InterNetwork,
+ SocketType.Stream, ProtocolType.Tcp);
+ IPEndPoint localEndPoint = new IPEndPoint(0, port);
+
+ // Bind the socket to the local endpoint and listen for incoming connections.
+ listener.Bind(localEndPoint);
+ listener.Listen(100);
+
+
+ // Start an asynchronous socket to listen for connections.
+ Console.WriteLine("Waiting for a connection...");
+ listener.BeginAccept(
+ new AsyncCallback(AcceptCallback),
+ listener);
+
+ }
+
+
+ public void AcceptCallback(IAsyncResult ar)
+ {
+
+ // Get the socket that handles the client request.
+ Socket listener = (Socket)ar.AsyncState;
+ listener.BeginAccept(
+ new AsyncCallback(AcceptCallback),
+ listener);
+
+ Socket conn = listener.EndAccept(ar);
+
+ // Create the state object.
+ Handler handler = new Handler();
+ handler.connection = conn;
+ handler.encryptor = encryptor;
+
+ handler.Start();
+ //handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
+ // new AsyncCallback(ReadCallback), state);
+ }
+
+ }
+
+ class Handler
+ {
+ public Encryptor encryptor;
+ // Client socket.
+ public Socket remote;
+ public Socket connection;
+ // Size of receive buffer.
+ public const int BufferSize = 1500;
+ // remote receive buffer
+ public byte[] remoteBuffer = new byte[BufferSize];
+ // connection receive buffer
+ public byte[] connetionBuffer = new byte[BufferSize];
+ // Received data string.
+ public StringBuilder sb = new StringBuilder();
+
+ public void Start()
+ {
+ // TODO async resolving
+ IPHostEntry ipHostInfo = Dns.GetHostEntry("127.0.0.1");
+ IPAddress ipAddress = ipHostInfo.AddressList[0];
+ IPEndPoint remoteEP = new IPEndPoint(ipAddress, 8388);
+
+
+ remote = new Socket(AddressFamily.InterNetwork,
+ SocketType.Stream, ProtocolType.Tcp);
+
+ // Connect to the remote endpoint.
+ remote.BeginConnect(remoteEP,
+ new AsyncCallback(connectCallback), null);
+ }
+
+ private void connectCallback(IAsyncResult ar)
+ {
+ try
+ {
+ // Complete the connection.
+ remote.EndConnect(ar);
+
+ Console.WriteLine("Socket connected to {0}",
+ remote.RemoteEndPoint.ToString());
+ Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
+
+ handshakeReceive();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ }
+
+ private void handshakeReceive()
+ {
+ try
+ {
+ connection.BeginReceive(new byte[256], 0, 256, 0,
+ new AsyncCallback(handshakeReceiveCallback), null);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ }
+
+ private void handshakeReceiveCallback(IAsyncResult ar)
+ {
+ try
+ {
+ int bytesRead = connection.EndReceive(ar);
+
+ if (bytesRead > 0)
+ {
+ byte[] response = { 5, 0 };
+ connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(handshakeSendCallback), null);
+ }
+ else
+ {
+ // TODO error
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ }
+
+ private void handshakeSendCallback(IAsyncResult ar)
+ {
+ try
+ {
+ connection.EndSend(ar);
+
+ // +----+-----+-------+------+----------+----------+
+ // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
+ // +----+-----+-------+------+----------+----------+
+ // | 1 | 1 | X'00' | 1 | Variable | 2 |
+ // +----+-----+-------+------+----------+----------+
+ // Skip first 3 bytes
+ // TODO validate
+ connection.BeginReceive(new byte[3], 0, 3, 0,
+ new AsyncCallback(handshakeReceive2Callback), null);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ }
+
+ private void handshakeReceive2Callback(IAsyncResult ar)
+ {
+ try
+ {
+ int bytesRead = connection.EndReceive(ar);
+
+ if (bytesRead > 0)
+ {
+ byte[] response = { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
+ connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(startPipe), null);
+ }
+ else
+ {
+ // TODO error
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ }
+
+
+ private void startPipe(IAsyncResult ar)
+ {
+ try
+ {
+ connection.EndReceive(ar);
+ remote.BeginReceive(remoteBuffer, 0, BufferSize, 0,
+ new AsyncCallback(pipeRemoteReceiveCallback), null);
+ connection.BeginReceive(connetionBuffer, 0, BufferSize, 0,
+ new AsyncCallback(pipeConnectionReceiveCallback), null);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ }
+
+ private void pipeRemoteReceiveCallback(IAsyncResult ar)
+ {
+
+ try
+ {
+ int bytesRead = remote.EndReceive(ar);
+
+ if (bytesRead > 0)
+ {
+ encryptor.Decrypt(remoteBuffer, bytesRead);
+ connection.BeginSend(remoteBuffer, 0, bytesRead, 0, new AsyncCallback(pipeConnectionSendCallback), null);
+ }
+ else
+ {
+ // TODO error
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ }
+
+ private void pipeConnectionReceiveCallback(IAsyncResult ar)
+ {
+
+ try
+ {
+ int bytesRead = connection.EndReceive(ar);
+
+ if (bytesRead > 0)
+ {
+ encryptor.Encrypt(connetionBuffer, bytesRead);
+ remote.BeginSend(connetionBuffer, 0, bytesRead, 0, new AsyncCallback(pipeRemoteSendCallback), null);
+ }
+ else
+ {
+ // TODO error
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ }
+
+ private void pipeRemoteSendCallback(IAsyncResult ar)
+ {
+ try
+ {
+ remote.EndSend(ar);
+ connection.BeginReceive(this.connetionBuffer, 0, BufferSize, 0,
+ new AsyncCallback(pipeConnectionReceiveCallback), null);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ }
+
+ private void pipeConnectionSendCallback(IAsyncResult ar)
+ {
+ try
+ {
+ connection.EndSend(ar);
+ remote.BeginReceive(this.remoteBuffer, 0, BufferSize, 0,
+ new AsyncCallback(pipeRemoteReceiveCallback), null);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ }
}
+
}
diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs
index 5da1a70e..d21d81aa 100755
--- a/shadowsocks-csharp/Program.cs
+++ b/shadowsocks-csharp/Program.cs
@@ -13,7 +13,7 @@ namespace shadowsocks_csharp
[STAThread]
static void Main()
{
- Test.Test1();
+ new Local(1081).Start();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj
index f6fc3c58..09d36023 100755
--- a/shadowsocks-csharp/shadowsocks-csharp.csproj
+++ b/shadowsocks-csharp/shadowsocks-csharp.csproj
@@ -6,12 +6,14 @@
9.0.21022
2.0
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}
- WinExe
+ Exe
Properties
shadowsocks_csharp
shadowsocks-csharp
v3.5
512
+
+
true