Merge branch 'disconnect'. Fixes #508
Conflicts: SparkleLib/SparkleListenerBase.cs SparkleLib/SparkleListenerTcp.cs
This commit is contained in:
commit
9f55680a6a
|
@ -16,6 +16,7 @@
|
|||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace SparkleLib {
|
||||
|
@ -23,28 +24,58 @@ namespace SparkleLib {
|
|||
public class SparkleGit : Process {
|
||||
|
||||
public static string ExecPath = null;
|
||||
public static string Path = null;
|
||||
|
||||
|
||||
public SparkleGit (string path, string args) : base ()
|
||||
{
|
||||
Path = LocateGit ();
|
||||
|
||||
EnableRaisingEvents = true;
|
||||
StartInfo.FileName = SparkleBackend.DefaultBackend.Path;
|
||||
StartInfo.FileName = Path;
|
||||
StartInfo.RedirectStandardOutput = true;
|
||||
StartInfo.UseShellExecute = false;
|
||||
StartInfo.WorkingDirectory = path;
|
||||
StartInfo.CreateNoWindow = true;
|
||||
|
||||
if (!string.IsNullOrEmpty (ExecPath))
|
||||
StartInfo.Arguments = "--exec-path=\"" + ExecPath + "\" " + args;
|
||||
else
|
||||
if (string.IsNullOrEmpty (ExecPath))
|
||||
StartInfo.Arguments = args;
|
||||
else
|
||||
StartInfo.Arguments = "--exec-path=\"" + ExecPath + "\" " + args;
|
||||
}
|
||||
|
||||
|
||||
new public void Start ()
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("Cmd", "git " + StartInfo.Arguments);
|
||||
base.Start ();
|
||||
|
||||
try {
|
||||
base.Start ();
|
||||
|
||||
} catch (Exception e) {
|
||||
SparkleHelpers.DebugInfo ("Cmd", "There's a problem running Git: " + e.Message);
|
||||
Environment.Exit (-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string LocateGit ()
|
||||
{
|
||||
if (!string.IsNullOrEmpty (Path))
|
||||
return Path;
|
||||
|
||||
string [] possible_git_paths = new string [] {
|
||||
"/usr/bin/git",
|
||||
"/usr/local/bin/git",
|
||||
"/opt/local/bin/git",
|
||||
"/usr/local/git/bin/git"
|
||||
};
|
||||
|
||||
foreach (string path in possible_git_paths)
|
||||
if (File.Exists (path))
|
||||
return path;
|
||||
|
||||
return "git";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
|
||||
namespace SparkleLib {
|
||||
|
||||
|
@ -167,25 +165,29 @@ namespace SparkleLib {
|
|||
}
|
||||
|
||||
|
||||
public override bool CheckForRemoteChanges ()
|
||||
public override bool HasRemoteChanges
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Checking for remote changes...");
|
||||
SparkleGit git = new SparkleGit (LocalPath, "ls-remote " + Url + " master");
|
||||
get {
|
||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Checking for remote changes...");
|
||||
SparkleGit git = new SparkleGit (LocalPath, "ls-remote " + Url + " master");
|
||||
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
if (git.ExitCode != 0)
|
||||
return false;
|
||||
if (git.ExitCode != 0)
|
||||
return false;
|
||||
|
||||
string remote_revision = git.StandardOutput.ReadToEnd ().TrimEnd ();
|
||||
string remote_revision = git.StandardOutput.ReadToEnd ().TrimEnd ();
|
||||
|
||||
if (!remote_revision.StartsWith (CurrentRevision)) {
|
||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Remote changes found. (" + remote_revision + ")");
|
||||
return true;
|
||||
if (!remote_revision.StartsWith (CurrentRevision)) {
|
||||
SparkleHelpers.DebugInfo ("Git",
|
||||
"[" + Name + "] Remote changes found. (" + remote_revision + ")");
|
||||
|
||||
} else {
|
||||
return false;
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ SOURCES = \
|
|||
Git/SparkleFetcherGit.cs \
|
||||
Git/SparkleGit.cs \
|
||||
Git/SparkleRepoGit.cs \
|
||||
SparkleAnnouncement.cs \
|
||||
SparkleBackend.cs \
|
||||
SparkleChangeSet.cs \
|
||||
SparkleConfig.cs \
|
||||
|
@ -13,6 +14,7 @@ SOURCES = \
|
|||
SparkleFetcherBase.cs \
|
||||
SparkleHelpers.cs \
|
||||
SparkleListenerBase.cs \
|
||||
SparkleListenerFactory.cs \
|
||||
SparkleListenerTcp.cs \
|
||||
SparkleRepoBase.cs \
|
||||
SparkleWatcher.cs
|
||||
|
|
34
SparkleLib/SparkleAnnouncement.cs
Normal file
34
SparkleLib/SparkleAnnouncement.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
namespace SparkleLib {
|
||||
|
||||
public class SparkleAnnouncement {
|
||||
|
||||
public readonly string FolderIdentifier;
|
||||
public readonly string Message;
|
||||
|
||||
|
||||
public SparkleAnnouncement (string folder_identifier, string message)
|
||||
{
|
||||
FolderIdentifier = folder_identifier;
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,40 +21,7 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace SparkleLib {
|
||||
|
||||
public class SparkleBackend {
|
||||
|
||||
public static SparkleBackend DefaultBackend = new SparkleBackendGit ();
|
||||
|
||||
public string Name;
|
||||
public string Path;
|
||||
|
||||
|
||||
public SparkleBackend (string name, string [] paths)
|
||||
{
|
||||
Name = name;
|
||||
Path = "git";
|
||||
|
||||
foreach (string path in paths) {
|
||||
if (File.Exists (path)) {
|
||||
Path = path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool IsPresent {
|
||||
get {
|
||||
return (Path != null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool IsUsablePath (string path)
|
||||
{
|
||||
return (path.Length > 0);
|
||||
}
|
||||
|
||||
public static class SparkleBackend {
|
||||
|
||||
public static string Version {
|
||||
get {
|
||||
|
@ -65,7 +32,7 @@ namespace SparkleLib {
|
|||
|
||||
// Strange magic needed by Platform ()
|
||||
[DllImport ("libc")]
|
||||
static extern int uname (IntPtr buf);
|
||||
private static extern int uname (IntPtr buf);
|
||||
|
||||
|
||||
// This fixes the PlatformID enumeration for MacOSX in Environment.OSVersion.Platform,
|
||||
|
@ -90,44 +57,4 @@ namespace SparkleLib {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class SparkleBackendGit : SparkleBackend {
|
||||
|
||||
private static string name = "Git";
|
||||
private static string [] paths = new string [] {
|
||||
"/opt/local/bin/git",
|
||||
"/usr/bin/git",
|
||||
"/usr/local/bin/git",
|
||||
"/usr/local/git/bin/git"
|
||||
};
|
||||
|
||||
public SparkleBackendGit () : base (name, paths) { }
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class SparkleBackendHg : SparkleBackend {
|
||||
|
||||
private static string name = "Hg";
|
||||
private static string [] paths = new string [] {
|
||||
"/opt/local/bin/hg",
|
||||
"/usr/bin/hg"
|
||||
};
|
||||
|
||||
public SparkleBackendHg () : base (name, paths) { }
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class SparkleBackendScp : SparkleBackend {
|
||||
|
||||
private static string name = "Scp";
|
||||
private static string [] paths = new string [] {
|
||||
"/usr/bin/scp"
|
||||
};
|
||||
|
||||
public SparkleBackendScp () : base (name, paths) { }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace SparkleLib {
|
|||
Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData),
|
||||
"sparkleshare");
|
||||
|
||||
// TODO: declare elsewhere
|
||||
public static SparkleConfig DefaultConfig = new SparkleConfig (default_config_path, "config.xml");
|
||||
public static bool DebugMode = true;
|
||||
|
||||
|
|
|
@ -16,9 +16,7 @@
|
|||
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.AccessControl;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
|
|
|
@ -40,12 +40,14 @@
|
|||
<Compile Include="Git/SparkleFetcherGit.cs" />
|
||||
<Compile Include="Hg/SparkleFetcherHg.cs" />
|
||||
<Compile Include="Defines.cs" />
|
||||
<Compile Include="SparkleAnnouncement.cs" />
|
||||
<Compile Include="SparkleHelpers.cs" />
|
||||
<Compile Include="SparklePaths.cs" />
|
||||
<Compile Include="SparkleOptions.cs" />
|
||||
<Compile Include="SparkleChangeSet.cs" />
|
||||
<Compile Include="SparkleListenerBase.cs" />
|
||||
<Compile Include="SparkleListenerIrc.cs" />
|
||||
<Compile Include="SparkleListenerFactory.cs" />
|
||||
<Compile Include="SparkleListenerTcp.cs" />
|
||||
<Compile Include="SparkleBackend.cs" />
|
||||
<Compile Include="SparkleConfig.cs" />
|
||||
<Compile Include="SparkleWatcher.cs" />
|
||||
|
|
|
@ -16,76 +16,11 @@
|
|||
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Timers;
|
||||
using System.Linq;
|
||||
|
||||
namespace SparkleLib {
|
||||
|
||||
public class SparkleAnnouncement {
|
||||
|
||||
public readonly string FolderIdentifier;
|
||||
public readonly string Message;
|
||||
|
||||
|
||||
public SparkleAnnouncement (string folder_identifier, string message)
|
||||
{
|
||||
FolderIdentifier = folder_identifier;
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class SparkleListenerFactory {
|
||||
|
||||
private static List<SparkleListenerBase> listeners = new List<SparkleListenerBase> ();
|
||||
|
||||
public static SparkleListenerBase CreateListener (string folder_name, string folder_identifier)
|
||||
{
|
||||
string uri = SparkleConfig.DefaultConfig.GetFolderOptionalAttribute (
|
||||
folder_name, "announcements_url");
|
||||
|
||||
if (uri == null) {
|
||||
// This is SparkleShare's centralized notification service.
|
||||
// Don't worry, we only use this server as a backup if you
|
||||
// don't have your own. All data needed to connect is hashed and
|
||||
// we don't store any personal information ever
|
||||
|
||||
uri = "tcp://notifications.sparkleshare.org:1986";
|
||||
}
|
||||
|
||||
Uri announce_uri = new Uri (uri);
|
||||
|
||||
// We use only one listener per server to keep
|
||||
// the number of connections as low as possible
|
||||
foreach (SparkleListenerBase listener in listeners) {
|
||||
if (listener.Server.Equals (announce_uri)) {
|
||||
SparkleHelpers.DebugInfo ("ListenerFactory",
|
||||
"Refered to existing listener for " + announce_uri);
|
||||
|
||||
listener.AlsoListenToBase (folder_identifier);
|
||||
return (SparkleListenerBase) listener;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new listener with the appropriate
|
||||
// type if one doesn't exist yet for that server
|
||||
switch (announce_uri.Scheme) {
|
||||
case "tcp":
|
||||
listeners.Add (new SparkleListenerTcp (announce_uri, folder_identifier));
|
||||
break;
|
||||
default:
|
||||
listeners.Add (new SparkleListenerTcp (announce_uri, folder_identifier));
|
||||
break;
|
||||
}
|
||||
|
||||
SparkleHelpers.DebugInfo ("ListenerFactory", "Issued new listener for " + announce_uri);
|
||||
return (SparkleListenerBase) listeners [listeners.Count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// A persistent connection to the server that
|
||||
// listens for change notifications
|
||||
public abstract class SparkleListenerBase {
|
||||
|
@ -170,6 +105,7 @@ namespace SparkleLib {
|
|||
}
|
||||
|
||||
|
||||
// TODO: rename override method instead?
|
||||
public void AlsoListenToBase (string channel)
|
||||
{
|
||||
if (!this.channels.Contains (channel) && IsConnected) {
|
||||
|
@ -210,9 +146,9 @@ namespace SparkleLib {
|
|||
}
|
||||
|
||||
|
||||
public void OnDisconnected ()
|
||||
public void OnDisconnected (string message)
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("Listener", "Signal of " + Server + " lost");
|
||||
SparkleHelpers.DebugInfo ("Listener", "Disconnected from " + Server + ": " + message);
|
||||
|
||||
if (Disconnected != null)
|
||||
Disconnected ();
|
||||
|
@ -294,4 +230,3 @@ namespace SparkleLib {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
89
SparkleLib/SparkleListenerFactory.cs
Normal file
89
SparkleLib/SparkleListenerFactory.cs
Normal file
|
@ -0,0 +1,89 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SparkleLib {
|
||||
|
||||
public static class SparkleListenerFactory {
|
||||
|
||||
private static List<SparkleListenerBase> listeners = new List<SparkleListenerBase> ();
|
||||
|
||||
|
||||
public static SparkleListenerBase CreateListener (string folder_name, string folder_identifier)
|
||||
{
|
||||
// Check if the user wants to use a global custom notification service
|
||||
string uri = SparkleConfig.DefaultConfig.GetConfigOption ("announcements_url");
|
||||
|
||||
// Check if the user wants a use a custom notification service for this folder
|
||||
if (string.IsNullOrEmpty (uri))
|
||||
uri = SparkleConfig.DefaultConfig.GetFolderOptionalAttribute (
|
||||
folder_name, "announcements_url");
|
||||
|
||||
// Fall back to the fallback service is neither is the case
|
||||
if (string.IsNullOrEmpty (uri)) {
|
||||
// This is SparkleShare's centralized notification service.
|
||||
// It communicates "It's time to sync!" signals between clients.
|
||||
//
|
||||
// Here's how it works: the client listens to a channel (the
|
||||
// folder identifier, a SHA-1 hash) for when it's time to sync.
|
||||
// Clients also send the current revision hash to the channel
|
||||
// for other clients to pick up when you've synced up any
|
||||
// changes.
|
||||
//
|
||||
// Please see the SparkleShare wiki if you wish to run
|
||||
// your own service instead
|
||||
|
||||
uri = "tcp://notifications.sparkleshare.org:1986";
|
||||
}
|
||||
|
||||
Uri announce_uri = new Uri (uri);
|
||||
|
||||
// We use only one listener per notification service to keep
|
||||
// the number of connections as low as possible
|
||||
foreach (SparkleListenerBase listener in listeners) {
|
||||
if (listener.Server.Equals (announce_uri)) {
|
||||
SparkleHelpers.DebugInfo ("ListenerFactory",
|
||||
"Refered to existing " + announce_uri.Scheme +
|
||||
" listener for " + announce_uri);
|
||||
|
||||
// We already seem to have a listener for this server,
|
||||
// refer to the existing one instead
|
||||
listener.AlsoListenToBase (folder_identifier);
|
||||
return (SparkleListenerBase) listener;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new listener with the appropriate
|
||||
// type if one doesn't exist yet for that server
|
||||
switch (announce_uri.Scheme) {
|
||||
case "tcp":
|
||||
listeners.Add (new SparkleListenerTcp (announce_uri, folder_identifier));
|
||||
break;
|
||||
default:
|
||||
listeners.Add (new SparkleListenerTcp (announce_uri, folder_identifier));
|
||||
break;
|
||||
}
|
||||
|
||||
SparkleHelpers.DebugInfo ("ListenerFactory",
|
||||
"Issued new " + announce_uri.Scheme + " listener for " + announce_uri);
|
||||
|
||||
return (SparkleListenerBase) listeners [listeners.Count - 1];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,23 +16,20 @@
|
|||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace SparkleLib {
|
||||
|
||||
public class SparkleListenerTcp : SparkleListenerBase {
|
||||
|
||||
private Socket socket;
|
||||
private Object socket_lock = new Object ();
|
||||
private Thread thread;
|
||||
private bool is_connected = false;
|
||||
private bool is_connecting = false;
|
||||
private Object socket_lock = new Object ();
|
||||
private bool is_connected = false;
|
||||
private bool is_connecting = false;
|
||||
private int receive_timeout = 180 * 1000;
|
||||
|
||||
|
||||
public SparkleListenerTcp (Uri server, string folder_identifier) :
|
||||
|
@ -60,83 +57,133 @@ namespace SparkleLib {
|
|||
// Starts a new thread and listens to the channel
|
||||
public override void Connect ()
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Connecting to " + Server.Host);
|
||||
|
||||
this.is_connecting = true;
|
||||
|
||||
this.thread = new Thread (
|
||||
new ThreadStart (delegate {
|
||||
int port = Server.Port;
|
||||
|
||||
if (port < 0)
|
||||
port = 1986;
|
||||
|
||||
try {
|
||||
// Connect and subscribe to the channel
|
||||
int port = Server.Port;
|
||||
|
||||
if (port < 0)
|
||||
port = 9999;
|
||||
|
||||
|
||||
lock (this.socket_lock) {
|
||||
this.socket = new Socket (AddressFamily.InterNetwork,
|
||||
SocketType.Stream, ProtocolType.Tcp) {
|
||||
|
||||
ReceiveTimeout = 30 * 1000
|
||||
ReceiveTimeout = this.receive_timeout,
|
||||
SendTimeout = 10 * 1000
|
||||
};
|
||||
|
||||
// Try to connect to the server
|
||||
this.socket.Connect (Server.Host, port);
|
||||
|
||||
this.is_connecting = false;
|
||||
this.is_connected = true;
|
||||
this.is_connected = true;
|
||||
|
||||
OnConnected ();
|
||||
|
||||
// Subscribe to channels of interest to us
|
||||
foreach (string channel in base.channels) {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Subscribing to channel " + channel);
|
||||
this.socket.Send (Encoding.UTF8.GetBytes ("subscribe " + channel + "\n"));
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp",
|
||||
"Subscribing to channel " + channel + " on " + Server);
|
||||
|
||||
byte [] subscribe_bytes =
|
||||
Encoding.UTF8.GetBytes ("subscribe " + channel + "\n");
|
||||
|
||||
this.socket.Send (subscribe_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
byte [] bytes = new byte [4096];
|
||||
|
||||
// List to the channels, this blocks the thread
|
||||
while (this.socket.Connected) {
|
||||
int bytes_read = this.socket.Receive (bytes);
|
||||
|
||||
if (bytes_read > 0) {
|
||||
string received = Encoding.UTF8.GetString (bytes);
|
||||
string line = received.Substring (0, received.IndexOf ("\n"));
|
||||
|
||||
if (!line.Contains ("!"))
|
||||
continue;
|
||||
|
||||
string folder_identifier = line.Substring (0, line.IndexOf ("!"));
|
||||
string message = CleanMessage (line.Substring (line.IndexOf ("!") + 1));
|
||||
|
||||
if (!folder_identifier.Equals ("debug") &&
|
||||
!String.IsNullOrEmpty (message)) {
|
||||
|
||||
OnAnnouncement (new SparkleAnnouncement (folder_identifier, message));
|
||||
}
|
||||
|
||||
} else {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Error on socket");
|
||||
|
||||
lock (this.socket_lock) {
|
||||
this.socket.Close ();
|
||||
this.is_connected = false;
|
||||
|
||||
OnDisconnected ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Disconnected from " + Server.Host);
|
||||
|
||||
} catch (SocketException e) {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Could not connect to " + Server + ": " + e.Message);
|
||||
this.is_connected = false;
|
||||
this.is_connected = false;
|
||||
this.is_connecting = false;
|
||||
|
||||
OnDisconnected ();
|
||||
OnDisconnected (e.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
byte [] bytes = new byte [4096];
|
||||
int bytes_read = 0;
|
||||
DateTime last_ping = DateTime.Now;
|
||||
|
||||
// Wait for messages
|
||||
while (this.is_connected) {
|
||||
try {
|
||||
// This blocks the thread
|
||||
bytes_read = this.socket.Receive (bytes);
|
||||
|
||||
// We've timed out, let's ping the server to
|
||||
// see if the connection is still up
|
||||
} catch (SocketException) {
|
||||
try {
|
||||
// Check when the last ping occured. If it's
|
||||
// significantly longer than our regular interval the
|
||||
// system likely woke up from sleep and we want to
|
||||
// simulate a disconnect
|
||||
int sleepiness = DateTime.Compare (
|
||||
last_ping.AddMilliseconds (this.receive_timeout * 1.25),
|
||||
DateTime.Now
|
||||
);
|
||||
|
||||
if (sleepiness <= 0) {
|
||||
// 10057 means "Socket is not connected"
|
||||
Console.WriteLine ("SLEEP OCCURED");
|
||||
throw new SocketException (10057);
|
||||
}
|
||||
|
||||
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Pinging " + Server);
|
||||
|
||||
byte [] ping_bytes = Encoding.UTF8.GetBytes ("ping\n");
|
||||
byte [] pong_bytes = new byte [4096];
|
||||
|
||||
lock (this.socket_lock)
|
||||
this.socket.Send (ping_bytes);
|
||||
|
||||
|
||||
this.socket.ReceiveTimeout = 10 * 1000;
|
||||
|
||||
if (this.socket.Receive (pong_bytes) < 1)
|
||||
// 10057 means "Socket is not connected"
|
||||
throw new SocketException (10057);
|
||||
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Received pong from " + Server);
|
||||
|
||||
|
||||
this.socket.ReceiveTimeout = this.receive_timeout;
|
||||
last_ping = DateTime.Now;
|
||||
|
||||
// The ping failed: disconnect completely
|
||||
} catch (SocketException) {
|
||||
this.is_connected = false;
|
||||
this.is_connecting = false;
|
||||
this.socket.ReceiveTimeout = this.receive_timeout;
|
||||
|
||||
OnDisconnected ("Ping timeout");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the received message
|
||||
if (bytes_read > 0) {
|
||||
string received = Encoding.UTF8.GetString (bytes);
|
||||
string line = received.Substring (0, received.IndexOf ("\n"));
|
||||
|
||||
if (!line.Contains ("!"))
|
||||
continue;
|
||||
|
||||
string folder_identifier = line.Substring (0, line.IndexOf ("!"));
|
||||
string message = CleanMessage (line.Substring (line.IndexOf ("!") + 1));
|
||||
|
||||
if (!folder_identifier.Equals ("debug") &&
|
||||
!String.IsNullOrEmpty (message)) {
|
||||
|
||||
// We have a message!
|
||||
OnAnnouncement (new SparkleAnnouncement (folder_identifier, message));
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
@ -150,18 +197,14 @@ namespace SparkleLib {
|
|||
string to_send = "subscribe " + folder_identifier + "\n";
|
||||
|
||||
try {
|
||||
lock (this.socket_lock) {
|
||||
lock (this.socket_lock)
|
||||
this.socket.Send (Encoding.UTF8.GetBytes (to_send));
|
||||
}
|
||||
|
||||
} catch (SocketException e) {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp",
|
||||
"Could not connect to " + Server + ": " + e.Message);
|
||||
|
||||
this.is_connected = false;
|
||||
this.is_connecting = false;
|
||||
|
||||
OnDisconnected ();
|
||||
OnDisconnected (e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,13 +219,10 @@ namespace SparkleLib {
|
|||
this.socket.Send (Encoding.UTF8.GetBytes (to_send));
|
||||
|
||||
} catch (SocketException e) {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp",
|
||||
"Could not connect to " + Server + ": " + e.Message);
|
||||
|
||||
this.is_connected = false;
|
||||
this.is_connecting = false;
|
||||
|
||||
OnDisconnected ();
|
||||
OnDisconnected (e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,7 +23,6 @@ using System.Text;
|
|||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Timers;
|
||||
using System.Xml;
|
||||
|
||||
namespace SparkleLib {
|
||||
|
||||
|
@ -41,21 +40,21 @@ namespace SparkleLib {
|
|||
private TimeSpan long_interval = new TimeSpan (0, 0, 10, 0);
|
||||
|
||||
private SparkleWatcher watcher;
|
||||
private SparkleListenerBase listener;
|
||||
private TimeSpan poll_interval;
|
||||
private System.Timers.Timer local_timer = new System.Timers.Timer () { Interval = 0.25 * 1000 };
|
||||
private System.Timers.Timer remote_timer = new System.Timers.Timer () { Interval = 10 * 1000 };
|
||||
private DateTime last_poll = DateTime.Now;
|
||||
private List<double> sizebuffer = new List<double> ();
|
||||
private bool has_changed = false;
|
||||
private Object change_lock = new Object ();
|
||||
private Object watch_lock = new Object ();
|
||||
private double progress_percentage = 0.0;
|
||||
private string progress_speed = "";
|
||||
private DateTime last_poll = DateTime.Now;
|
||||
private List<double> size_buffer = new List<double> ();
|
||||
private bool has_changed = false;
|
||||
private Object change_lock = new Object ();
|
||||
private Object watch_lock = new Object ();
|
||||
private double progress_percentage = 0.0;
|
||||
private string progress_speed = "";
|
||||
private SyncStatus status;
|
||||
|
||||
protected SparkleListenerBase listener;
|
||||
protected SyncStatus status;
|
||||
protected bool is_buffering = false;
|
||||
protected bool server_online = true;
|
||||
private bool is_buffering = false;
|
||||
private bool server_online = true;
|
||||
|
||||
public readonly string LocalPath;
|
||||
public readonly string Name;
|
||||
|
@ -68,6 +67,7 @@ namespace SparkleLib {
|
|||
public abstract bool SyncDown ();
|
||||
public abstract double CalculateSize (DirectoryInfo parent);
|
||||
public abstract bool HasUnsyncedChanges { get; set; }
|
||||
public abstract bool HasRemoteChanges { get; }
|
||||
public abstract List<string> ExcludePaths { get; }
|
||||
|
||||
public abstract double Size { get; }
|
||||
|
@ -121,7 +121,7 @@ namespace SparkleLib {
|
|||
if (time_to_poll) {
|
||||
this.last_poll = DateTime.Now;
|
||||
|
||||
if (CheckForRemoteChanges ())
|
||||
if (HasRemoteChanges)
|
||||
SyncDownBase ();
|
||||
}
|
||||
|
||||
|
@ -191,6 +191,7 @@ namespace SparkleLib {
|
|||
|
||||
public string Domain {
|
||||
get {
|
||||
// TODO: use Uri class
|
||||
Regex regex = new Regex (@"(@|://)([a-z0-9\.-]+)(/|:)");
|
||||
Match match = regex.Match (SparkleConfig.DefaultConfig.GetUrlForFolder (Name));
|
||||
|
||||
|
@ -211,12 +212,6 @@ namespace SparkleLib {
|
|||
}
|
||||
|
||||
|
||||
public virtual bool CheckForRemoteChanges () // TODO: HasRemoteChanges { get; }
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public virtual List<SparkleChangeSet> GetChangeSets (int count) {
|
||||
return null;
|
||||
}
|
||||
|
@ -270,7 +265,7 @@ namespace SparkleLib {
|
|||
this.poll_interval = this.long_interval;
|
||||
|
||||
new Thread (new ThreadStart (delegate {
|
||||
if (!IsSyncing && CheckForRemoteChanges ())
|
||||
if (!IsSyncing && HasRemoteChanges)
|
||||
SyncDownBase ();
|
||||
})).Start ();
|
||||
}
|
||||
|
@ -283,7 +278,7 @@ namespace SparkleLib {
|
|||
if (!IsSyncing) {
|
||||
|
||||
// Check for changes manually one more time
|
||||
if (CheckForRemoteChanges ())
|
||||
if (HasRemoteChanges)
|
||||
SyncDownBase ();
|
||||
|
||||
// Push changes that were made since the last disconnect
|
||||
|
@ -336,16 +331,16 @@ namespace SparkleLib {
|
|||
{
|
||||
lock (this.change_lock) {
|
||||
if (this.has_changed) {
|
||||
if (this.sizebuffer.Count >= 4)
|
||||
this.sizebuffer.RemoveAt (0);
|
||||
if (this.size_buffer.Count >= 4)
|
||||
this.size_buffer.RemoveAt (0);
|
||||
|
||||
DirectoryInfo dir_info = new DirectoryInfo (LocalPath);
|
||||
this.sizebuffer.Add (CalculateSize (dir_info));
|
||||
this.size_buffer.Add (CalculateSize (dir_info));
|
||||
|
||||
if (this.sizebuffer.Count >= 4 &&
|
||||
this.sizebuffer [0].Equals (this.sizebuffer [1]) &&
|
||||
this.sizebuffer [1].Equals (this.sizebuffer [2]) &&
|
||||
this.sizebuffer [2].Equals (this.sizebuffer [3])) {
|
||||
if (this.size_buffer.Count >= 4 &&
|
||||
this.size_buffer [0].Equals (this.size_buffer [1]) &&
|
||||
this.size_buffer [1].Equals (this.size_buffer [2]) &&
|
||||
this.size_buffer [2].Equals (this.size_buffer [3])) {
|
||||
|
||||
SparkleHelpers.DebugInfo ("Local", "[" + Name + "] Changes have settled.");
|
||||
this.is_buffering = false;
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace SparkleShare {
|
|||
|
||||
|
||||
// Let's use the bundled git first
|
||||
SparkleBackend.DefaultBackend.Path =
|
||||
SparkleGit.Path =
|
||||
Path.Combine (NSBundle.MainBundle.ResourcePath,
|
||||
"git", "libexec", "git-core", "git");
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace SparkleShare {
|
|||
|
||||
public SparkleStatusIconController Controller = new SparkleStatusIconController ();
|
||||
|
||||
// TODO: Fix case
|
||||
private Timer Animation;
|
||||
private int FrameNumber;
|
||||
private string StateText;
|
||||
|
|
|
@ -40,9 +40,6 @@ namespace SparkleShare {
|
|||
public double ProgressPercentage = 0.0;
|
||||
public string ProgressSpeed = "";
|
||||
|
||||
public event OnQuitWhileSyncingHandler OnQuitWhileSyncing;
|
||||
public delegate void OnQuitWhileSyncingHandler ();
|
||||
|
||||
public event FolderFetchedEventHandler FolderFetched;
|
||||
public delegate void FolderFetchedEventHandler (string [] warnings);
|
||||
|
||||
|
@ -783,13 +780,6 @@ namespace SparkleShare {
|
|||
}
|
||||
|
||||
|
||||
public bool BackendIsPresent {
|
||||
get {
|
||||
return SparkleBackend.DefaultBackend.IsPresent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Looks up the user's name from the global configuration
|
||||
public string UserName
|
||||
{
|
||||
|
@ -1116,9 +1106,6 @@ namespace SparkleShare {
|
|||
repo.Status == SyncStatus.SyncDown ||
|
||||
repo.IsBuffering) {
|
||||
|
||||
if (OnQuitWhileSyncing != null)
|
||||
OnQuitWhileSyncing ();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,12 +63,9 @@ namespace SparkleShare {
|
|||
Setup = new SparkleSetup ();
|
||||
Setup.Controller.ShowSetupPage ();
|
||||
}
|
||||
|
||||
Program.Controller.OnQuitWhileSyncing += delegate {
|
||||
// TODO: Pop up a warning when quitting whilst syncing
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Runs the application
|
||||
public void Run ()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue