diff --git a/AutoShare/App.config b/AutoShare/App.config
index 577b805..159dd34 100644
--- a/AutoShare/App.config
+++ b/AutoShare/App.config
@@ -23,6 +23,9 @@
userlist
+
+ 12344
+
@@ -38,6 +41,9 @@
True
+
+ users.temp
+
\ No newline at end of file
diff --git a/AutoShare/App.xaml b/AutoShare/App.xaml
index 2f8e194..fcab8d9 100644
--- a/AutoShare/App.xaml
+++ b/AutoShare/App.xaml
@@ -1,6 +1,7 @@

diff --git a/AutoShare/App.xaml.cs b/AutoShare/App.xaml.cs
index 3d0c9de..ea1e283 100644
--- a/AutoShare/App.xaml.cs
+++ b/AutoShare/App.xaml.cs
@@ -9,7 +9,9 @@
using System.IO;
using System.Windows.Shapes;
using System.Security.Permissions;
-
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Runtime.Serialization;
+using AutoShare.Engine.Network.Sharing;
namespace AutoShare
{
@@ -19,14 +21,25 @@ namespace AutoShare
public partial class App : Application
{
public AutoShare.Engine.IO.FilesFolderChecker FolderWatchdog;
- public AutoShare.Engine.IO.SerializableList KnownUsers;
-
+ public AutoShare.Engine.IO.SerializableList KnownUsers;
+ public AutoShare.Engine.Network.NetworkClient Client;
+ public AutoShare.Engine.Network.NetworkServer Server;
//TEMP
public bool AskUserExit = true;
App()
{
#region Initialization Block
+ KnownUsers = new Engine.IO.SerializableList();
+ /** UNCOMMENT TO CREATE TEST USERINFO
+ *
+ *
+ UserInfo self = new UserInfo("TestBuddy", "Apple", new System.Net.IPEndPoint(new System.Net.IPAddress(new byte[4]{127,0,0,1}),4321), true);
+ KnownUsers.List.Add(self);
+ */
+ Client = new Engine.Network.NetworkClient();
+ Server = new Engine.Network.NetworkServer(4321);
+
string path;
if (AutoShare.Properties.Settings.Default.UseDocFolder)
path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + System.IO.Path.DirectorySeparatorChar + AutoShare.Properties.Settings.Default.FolderPath;
@@ -35,21 +48,71 @@ public partial class App : Application
FolderWatchdog = new Engine.IO.FilesFolderChecker(path, true);
- KnownUsers = new Engine.IO.SerializableList();
+
#endregion
#region Subscription to events
#endregion
+ #region Network Startup
+
+
+ #endregion
+ this.Initialize();
+
+
+ //TEMP just for testing purposes
+
+
+
+ }
+ public void Initialize()
+ {
+ //TEMP as the Initialize() function is described in the paper
+ BinaryFormatter formatter = new BinaryFormatter();
+ string Path = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + System.IO.Path.DirectorySeparatorChar +
+ AutoShare.Properties.Settings.Default.UserlistPrefix + System.Environment.UserName + '.' + AutoShare.Properties.Settings.Default.UserlistExtension;
+ using (FileStream tfs = new FileStream(Path, FileMode.Open, FileAccess.Read))
+ KnownUsers = (AutoShare.Engine.IO.SerializableList)formatter.Deserialize(tfs);
+
}
- public void Shutdown()
+ public new void Shutdown()
{
//save all settings
AutoShare.Properties.Settings.Default.Save();
//save folder state
//save user state
+ //TEMP (because user can change its name, need to make login system)
+ string CurrentUserName = System.Environment.UserName;
+ //filepath
+ string Path = AutoShare.Properties.Settings.Default.UserlistPrefix + CurrentUserName + '.' + AutoShare.Properties.Settings.Default.UserlistExtension;
+ string TempPath = AutoShare.Properties.Settings.Default.TemporaryUserlistName + '.' + AutoShare.Properties.Settings.Default.UserlistExtension;
+ //get save path
+ BinaryFormatter formatter = new BinaryFormatter();
+ //TEMP as can be failed/access denied/program halted during I/O operation etc. Need to write first in a temp file, then rewrite, then delete temp file.
+ //1. Save to temp folder
+ using( FileStream tfs = new FileStream(TempPath, FileMode.Create, FileAccess.Write) )
+ formatter.Serialize(tfs, KnownUsers,
+ new System.Runtime.Remoting.Messaging.Header[1]{ new System.Runtime.Remoting.Messaging.Header("USERLISTLENGTH", KnownUsers.List.Count ) } );
+ //2. Overwrite
+ File.Copy( TempPath, System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + System.IO.Path.DirectorySeparatorChar + Path, true );
+
+
+ //Dispose all the resources
+ this.Server.Dispose();
+ //Finally, shutdown itself
+ base.Shutdown();
+
}
+
+ //END CLASS <>
}
+
+
+
+
+
+ //END APP.XAML.CS
}
diff --git a/AutoShare/AutoShare.csproj b/AutoShare/AutoShare.csproj
index 384d941..c8ba542 100644
--- a/AutoShare/AutoShare.csproj
+++ b/AutoShare/AutoShare.csproj
@@ -71,7 +71,7 @@
-
+
diff --git a/AutoShare/Engine/Network/AutoClient.cs b/AutoShare/Engine/Network/AutoClient.cs
deleted file mode 100644
index c744992..0000000
--- a/AutoShare/Engine/Network/AutoClient.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Net.Sockets;
-using System.Threading;
-
-
-namespace AutoShare.Engine.Network
-{
- public class Node {
- System.Net.EndPoint EndPoint;
- string EncryptionKey;
- }
-
- public class Helper
- {
- static int DefaultServerPort = 4321;
- }
-
- public class Client
- {
- TcpClient tcp_client;
- List task;
- List nodes;
- Client()
- {
-
- }
- void AddNode(Node node){
-
- }
- Node this[int i]
- {
- get
- {
- return nodes[i];
- }
- }
- ~Client()
- {
-
- }
- }
-}
diff --git a/AutoShare/Engine/Network/NetworkClient.cs b/AutoShare/Engine/Network/NetworkClient.cs
new file mode 100644
index 0000000..374f631
--- /dev/null
+++ b/AutoShare/Engine/Network/NetworkClient.cs
@@ -0,0 +1,173 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Net.Sockets;
+using System.Threading;
+using AutoShare.Engine.Network.Sharing;
+
+namespace AutoShare.Engine.Network
+{
+ //TODO: MOVE LIST outside of class. To sync values from the server and from the client
+
+ public class NetworkClient
+ {
+ #region Helper Classes
+ public struct UserStatus
+ {
+ public UserInfo Info;
+ public DateTime LastPinged;
+ public bool IsOnline;
+
+
+ public UserStatus(UserInfo Info, DateTime LastPinged, bool IsOnline)
+ {
+ this.Info = Info;
+ this.LastPinged = LastPinged;
+ this.IsOnline = IsOnline;
+ }
+
+ }
+
+ #endregion
+ #region Private Members
+ List task;
+ ManualResetEvent mres;
+ List socket_threads;
+ List nodes; //ping nodes
+
+ #endregion
+ #region Thread Functions
+
+ void SocketThread(object index)
+ {
+ TcpClient cli = null;
+ UserStatus us;
+ try {
+
+ lock (nodes)
+ us = nodes[(int)index];
+ cli = new TcpClient();
+ //BEFORE FIRST
+ cli.NoDelay = false;
+ cli.ReceiveTimeout = 10;
+ cli.SendTimeout = 5;
+ //FIRST - connect to the last known
+ cli.Connect(us.Info.LastKnownAddress);
+ //SECOND - cycle through the known ip addresses
+ if (!cli.Connected)
+ {
+ for (int i = 0, s = us.Info.AddressHistory.Count; i < s; ++i)
+ {
+ cli.Connect(us.Info.AddressHistory[i].EndPoint);
+ if (cli.Connected)
+ break;
+ }
+ }
+ //THIRD - EITHER DIE WITH NO STATE OR CONNECT AND SYNC LIST
+ us.LastPinged = DateTime.Now;
+ //TEMP just a workaround
+ us.IsOnline = cli.Connected;
+ if (us.IsOnline)
+ {
+ //TEMP: Send something
+ NetworkStream ns = cli.GetStream();
+ byte[] bytes = System.Text.UTF8Encoding.UTF8.GetBytes("PING");
+ ns.Write( bytes, 0, bytes.Length );
+ ns.Close();
+ }
+ }
+ catch (ThreadAbortException) {
+
+ }
+ finally {
+ //set thread running to false
+ if(cli!=null)
+ cli.Close();
+
+ }
+
+
+
+
+ //END
+
+ }
+
+ #endregion
+ #region Constructor and Destructors
+ public NetworkClient(IEnumerable UserStatuses = null, bool StartImmediately = true)
+ {
+ if (UserStatuses != null && UserStatuses.Count() > 0)
+ nodes = new List(UserStatuses);
+ else
+ nodes = new List();
+ socket_threads = new List();
+ mres = new ManualResetEvent(false);
+ if (nodes.Count > 0)
+ {
+ for (int i = 0, s = nodes.Count; i < s; ++i )
+ AddThread(true);
+ }
+ }
+
+ ~NetworkClient()
+ {
+ mres.Set();
+ //Delay for dispose
+ mres.WaitOne();
+ //Dispose object
+ mres.Dispose();
+ }
+
+ #endregion
+ #region Protected Methods
+ protected void AddThread(bool StartImmediately)
+ {
+ Thread thr = new Thread(SocketThread);
+ lock (this.socket_threads)
+ {
+ this.socket_threads.Add(thr);
+ if (StartImmediately)
+ thr.Start(this.socket_threads.Count - 1);
+ }
+
+ }
+ #endregion
+
+ #region API Calls and Public Accessors
+ public void AddNode(UserStatus UserStatus, bool StartImmediately = true)
+ {
+ lock (this.nodes)
+ {
+ this.nodes.Add(UserStatus);
+ this.AddThread(StartImmediately);
+ }
+ }
+ public void RemoveNode(int index)
+ {
+ this.nodes.RemoveAt(index);
+ this.socket_threads[index].Abort();
+ this.socket_threads.RemoveAt(index);
+ }
+ public UserStatus this[int i] { get { return nodes[i]; } set { nodes[i] = value; } }
+
+ public ThreadState NodeThreadState(int i)
+ {
+ return this.socket_threads[i].ThreadState;
+ }
+
+ public void StartNodeThread(int i)
+ {
+ this.socket_threads[i].Start();
+ }
+
+ public void StopNodeThread(int i)
+ {
+ //TEMP and workaround. Recode this thing
+ this.socket_threads[i].Abort();
+ }
+ #endregion
+ }
+}
diff --git a/AutoShare/Engine/Network/NetworkServer.cs b/AutoShare/Engine/Network/NetworkServer.cs
index 210e068..9d4334d 100644
--- a/AutoShare/Engine/Network/NetworkServer.cs
+++ b/AutoShare/Engine/Network/NetworkServer.cs
@@ -9,14 +9,40 @@
namespace AutoShare.Engine.Network
{
- public class NetworkServer
+ public class NetworkServer:IDisposable
{
#region
TcpListener Listener; // Îáúåêò, ïðèíèìàþùèé TCP-êëèåíòîâ
ManualResetEvent HEvent;
List ProcessingThreads;
Thread ServerThread;
+ bool Disposed; //Ïîêàçûâàåò, ðàáî÷èé ëè îáúåêò êëàññà íà äàííûé ìîìåíò
+ #endregion
+
+
+ #region Protected Functions
+ void DisposeImplemention()
+ {
+ if (!Disposed)
+ {
+ this.HEvent.Set();
+ for (int i = 0, s = ProcessingThreads.Count; i < s; ++i)
+ ProcessingThreads[i].Abort(); //TODO either remove this madness or make another approach as the processing thread could be running long and is NOT a critical (means important) thread
+
+ Disposed = true;
+ }
+
+
+ }
+
+ void Resurrect()
+ {
+ if (Disposed)
+ {
+ //TODO - ressurect
+ }
+ }
#endregion
#region Threading Functions
void ProcessClientThreadingFunction(object client)
@@ -33,9 +59,12 @@ void ProcessClientThreadingFunction(object client)
NetworkStream ns = cli.GetStream();
byte[] bytes_to_send, buffer = new byte[NetPacket.PacketSignatureRule.MaxSignatureSize];
//Accept the signature and some data (probably)
- ns.Read(buffer, 0, buffer.Length);
-
+ int nbytes = cli.Available;
+ ns.Read(buffer, 0, nbytes);
//TEMP
+ if (System.Text.UTF8Encoding.UTF8.GetString(buffer, 0, nbytes) == "PING")
+ this.DispatchEvent(this.PingReceived);
+
bytes_to_send = System.Text.UTF8Encoding.UTF8.GetBytes("PONG");
//Final Function
ns.Write(bytes_to_send, 0, bytes_to_send.Length);
@@ -54,19 +83,37 @@ void ServerThreadFunction()
{
Listener.Start();
Listener.BeginAcceptTcpClient( (IAsyncResult res)=>{
- TcpClient cli = Listener.EndAcceptTcpClient(res);
- if(cli!=null){
- Thread thr = new Thread(ProcessClientThreadingFunction);
- ProcessingThreads.Add(thr);
- thr.Start( cli );
+ try
+ {
+ TcpClient cli = Listener.EndAcceptTcpClient(res);
+ if (cli != null)
+ {
+ Thread thr = new Thread(ProcessClientThreadingFunction);
+ ProcessingThreads.Add(thr);
+ thr.Start(cli);
+ }
+ }
+ catch (ObjectDisposedException){
+ //ok, socket was disposed outside the code
}
+
}, null);
this.HEvent.WaitOne();
Listener.Stop();
}
#endregion
-
+ #region Public Events and Event Dispatchers
+ public event EventHandler AcceptedClient;
+ //TEMP temporary event just for testing purposes (maybe add a META HEAD "TEST"?)
+ //TEST Yeah, maybe
+ public event EventHandler PingReceived;
+ protected void DispatchEvent(Delegate Event, object value = null)
+ {
+ if (Event != null)
+ Event.DynamicInvoke(this, value??new EventArgs());
+ }
+ #endregion
#region Constructors and Destructors
//Çàïóñê Ñåðâåðà
public NetworkServer(int Port, bool StartImmediately = true)
@@ -82,12 +129,11 @@ public NetworkServer(int Port, bool StartImmediately = true)
}
+
// Îñòàíîâêà ñåðâåðà
~NetworkServer()
{
- this.HEvent.Set();
- for (int i = 0, s = ProcessingThreads.Count; i < s; ++i )
- ProcessingThreads[i].Abort();
+ this.DisposeImplemention();
}
#endregion
#region API Calls
@@ -98,6 +144,11 @@ public void Start()
ServerThread.Start();
}
}
+
+ public void Dispose()
+ {
+ this.DisposeImplemention();
+ }
#endregion
}
}
\ No newline at end of file
diff --git a/AutoShare/Engine/Network/Sharing/UserInfo.cs b/AutoShare/Engine/Network/Sharing/UserInfo.cs
index 61bfdd4..0634e59 100644
--- a/AutoShare/Engine/Network/Sharing/UserInfo.cs
+++ b/AutoShare/Engine/Network/Sharing/UserInfo.cs
@@ -166,14 +166,14 @@ public void GetObjectData(SerializationInfo info, StreamingContext context)
#endregion
#region Properties
//Changes frequently
- System.Net.IPEndPoint LastKnownAddress { get { return _addr; } }
- bool StrictNATDetected { get { return _strict_nat; } }
+ public System.Net.IPEndPoint LastKnownAddress { get { return _addr; } }
+ public bool StrictNATDetected { get { return _strict_nat; } set { _strict_nat = value; } }
//Almost Hardcoded
- string EvaluationKey { get { return _eval_key; } }
- string UserName { get { return _name; } }
+ public string EvaluationKey { get { return _eval_key; } }
+ public string UserName { get { return _name; } }
//Historical
- bool LogChangeIPs { get { return this._log_ips; } }
- List AddressHistory { get { return this._addr_history; } }
+ public bool LogChangeIPs { get { return this._log_ips; } }
+ public List AddressHistory { get { return this._addr_history; } }
#endregion
#region Private methods
diff --git a/AutoShare/MainWindow.xaml.cs b/AutoShare/MainWindow.xaml.cs
index b243ee1..8c9e5c0 100644
--- a/AutoShare/MainWindow.xaml.cs
+++ b/AutoShare/MainWindow.xaml.cs
@@ -35,8 +35,23 @@ public MainWindow()
UsersModel = new ObservableCollection((App.Current as App).KnownUsers.List);
UsersDataGrid.ItemsSource = UsersModel;
UsersModel.CollectionChanged += UsersModel_CollectionChanged;
+
+ //TEST for testing purposes
+ if ((App.Current as App).KnownUsers.List.Count > 0)
+ {
+ (App.Current as App).Server.PingReceived += Server_PingReceived;
+ (App.Current as App).Client.AddNode(new Engine.Network.NetworkClient.UserStatus((App.Current as App).KnownUsers.List[0], DateTime.MinValue, false));
+ }
+
}
+ void Server_PingReceived(object sender, EventArgs e)
+ {
+
+ this.Dispatcher.BeginInvoke(new Action(() => { this.ShowMessageAsync("OLOLO", "Received from someone PING message", MessageDialogStyle.Affirmative); }));
+ }
+
+
void UsersModel_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
//throw new NotImplementedException();
@@ -103,7 +118,8 @@ private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
this.ShowBinaryDialog("There are actions preventing to close the application. Do you really want to exit?", "Exit Confirmation" , () => {
this.Dispatcher.BeginInvoke(new Action(() => {
this.Closing -= OnClosing;
- this.Close();
+ this.Close();
+ (App.Current as App).Shutdown();
}));
});
}
diff --git a/AutoShare/Properties/Settings.Designer.cs b/AutoShare/Properties/Settings.Designer.cs
index ca5df15..3d49107 100644
--- a/AutoShare/Properties/Settings.Designer.cs
+++ b/AutoShare/Properties/Settings.Designer.cs
@@ -61,5 +61,26 @@ public string UserlistExtension {
return ((string)(this["UserlistExtension"]));
}
}
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("12344")]
+ public int ServerPort {
+ get {
+ return ((int)(this["ServerPort"]));
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("users.temp")]
+ public string TemporaryUserlistName {
+ get {
+ return ((string)(this["TemporaryUserlistName"]));
+ }
+ set {
+ this["TemporaryUserlistName"] = value;
+ }
+ }
}
}
diff --git a/AutoShare/Properties/Settings.settings b/AutoShare/Properties/Settings.settings
index 5730e7b..c0fc3f1 100644
--- a/AutoShare/Properties/Settings.settings
+++ b/AutoShare/Properties/Settings.settings
@@ -14,5 +14,11 @@
userlist
+
+ 12344
+
+
+ users.temp
+
\ No newline at end of file