summaryrefslogtreecommitdiff
path: root/src/tmate/session.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/tmate/session.vala')
-rw-r--r--src/tmate/session.vala252
1 files changed, 108 insertions, 144 deletions
diff --git a/src/tmate/session.vala b/src/tmate/session.vala
index 356aa66..fae55b6 100644
--- a/src/tmate/session.vala
+++ b/src/tmate/session.vala
@@ -2,122 +2,81 @@ namespace Tmate
{
public interface SessionInterface : Object
{
- public abstract signal void address (SessionType session, string address);
-
- public abstract string? @get(SessionType session);
- public abstract bool start(string? config = null);
+ public abstract signal void started (string socket);
+ public abstract signal void stopped ();
+ public abstract signal void address_changed (SessionType session, string address);
+ public abstract signal void error (string summery, string message = "");
+ public abstract signal void joined (string mate, int mates);
+ public abstract signal void left (string mate, int mates);
+
+ public abstract bool start(Config? config = null);
public abstract bool stop();
}
[SingleInstance]
public class Session: Object, SessionInterface
{
- private string? _addr_ssh = null;
- private string? _addr_http = null;
- private string? _addr_ssh_ro = null;
- private string? _addr_http_ro = null;
- private IOChannel? stdout = null;
- private Pid? pid = null;
- private uint error_count = 0;
-
- // Regex
- private Regex r_connect = /^Connecting to .+\.\.\.$/;
- private Regex r_socket = /^To connect.+ tmate -S (.+) attach$/;
- private Regex r_http = /^web \w+[:] (.+)$/;
- private Regex r_ssh = /^ssh \w+[:] .+ (.+)+$/;
- private Regex r_http_ro = /^web \w+ read \w+[:] (.+)$/;
- private Regex r_ssh_ro = /^ssh \w+ read \w+[:] .+ (.+)+$/;
- private Regex r_joined = /^.+ joined \(([^()]+)\) -- (\d+) clients? .+$/;
- private Regex r_left = /^.+ left \(([^()]+)\) -- (\d+) clients? .+$/;
- private Regex r_closed = /^Session closed$/;
- private Regex r_note = /^(Note: |Reconnecting)/;
- private Regex r_restarted = /^Session shell restarted$/;
- private Regex r_netfail= /^[^ ]+ lookup failure\..+ \((.+)\)$/;
-
- public SessionType flags { get; private set;}
- public string? socket { get; private set;}
- public bool terminate = true;
-
- construct { reset(); }
-
- public virtual signal void started (string socket)
- {
- info (_("Session: unix://%s"), socket);
- }
+ private IOChannel? stdout = null;
+ private Pid? pid = null;
+ private uint error_count = 0;
- public virtual signal void network_error(string message)
- {
- if(error_count ++ > 5) stop();
- }
+ public bool terminate = true;
+ public SessionAddress address { get; construct; }
+ public string? socket { get; private set;}
+ public Config? config { get; private set;}
- public virtual signal void stopped ()
- {
- info (_("Session terminated."));
+ construct {
+ address = new SessionAddress();
reset();
+ address.clear();
+ error.connect_after(() => {
+ if(error_count++ < 5) return;
+
+ stop();
+ });
}
- private void address_set(SessionType session, string address)
+ private void address_set(SessionType session, string? address)
{
- info (_("%s address: %s"), session.to_string(), address);
-
- if (session in SessionType.SSH|SessionType.SSH_READONLY|SessionType.HTTP|SessionType.HTTP_READONLY) {
- switch(session) {
- case SSH:
- _addr_ssh = address;
- break;
- case HTTP:
- _addr_http = address;
- break;
- case HTTP_READONLY:
- _addr_http_ro = address;
- break;
- case SSH_READONLY :
- _addr_ssh_ro = address;
- break;
- default:
- warn_if_reached();
- break;
- }
-
- flags |= session;
- this.address(session, address);
- } else if (session == DISCONNECTED) {
- _addr_http = _addr_ssh = _addr_http_ro = _addr_ssh_ro = null;
- flags = DISCONNECTED;
- this.address(DISCONNECTED, "");
+ if (SessionType.SSH in session || SessionType.HTTP in session) {
+ debug("CALL: %s\t%s", session.to_string(), address);
+ if(address != null || address != "")
+ this.address.add(session, address);
+
+ if(this.address[session] != null)
+ address_changed (session, this.address[session]);
}
}
- public virtual signal void joined (string mate, int mates)
- {
- info(_("%s joined, connected: %d"), mate, mates);
- }
- public virtual signal void left (string mate, int mates)
+
+ private void reset()
{
- info(_("%s left, connected: %d"), mate, mates);
+ stdout = null;
+ pid = null;
+ socket = null;
+ error_count = 0;
+ address.clear();
+ delete_config();
}
- private void reset()
+ internal void delete_config()
{
- _addr_ssh = null;
- _addr_http = null;
- _addr_ssh_ro = null;
- _addr_http_ro = null;
- stdout = null;
- pid = null;
- socket = null;
- flags = DISCONNECTED;
- error_count = 0;
+ if(null == config) return;
+
+ config.delete();
+ config = null;
}
private bool send(string[] args)
{
- if(socket == null)
+ if(pid == null)
return false;
+
var command = new GenericArray<string>();
command.data = {
"/usr/bin/tmate",
"-S", socket
};
+
foreach(var arg in args)
command.add(arg);
@@ -131,50 +90,38 @@ namespace Tmate
}
- public new string? @get(SessionType session)
+ private void restart()
{
- switch(session) {
- case SSH:
- return _addr_ssh;
- case HTTP:
- return _addr_http;
- case SSH_READONLY :
- return _addr_ssh_ro;
- case HTTP_READONLY:
- return _addr_http_ro;
- case DISCONNECTED :
- warning("No running session.");
- break;
- default:
- warning("Unknown Session Type %s", session.to_string());
- break;
+ if(terminate) {
+ stop();
+ return;
}
- return null;
+ started(socket);
+ address_set(SSH, null);
+ address_set(HTTP, null);
+ address_set(SSH | READONLY, null);
+ address_set(HTTP | READONLY, null);
}
public bool stop()
{
- return send({"kill-server"});
- }
-
- private void restart()
- {
- if(terminate) {
- stop();
- return;
+ debug("stopping!");
+ var ret = send({"kill-server"});
+ if (! send({"has"})) {
+ debug("stopped!");
+ Idle.add(() => {
+ stopped();
+ return false;
+ });
}
- started(socket);
- if((bool)_addr_ssh) address(SSH, _addr_ssh);
- if((bool)_addr_ssh_ro) address(SSH_READONLY, _addr_ssh_ro);
- if((bool)_addr_http) address(HTTP, _addr_http);
- if((bool)_addr_http_ro) address(HTTP_READONLY, _addr_http_ro);
+ return ret;
}
- public bool start(string? config = null)
+ public bool start(Config? config = null)
{
- if(! (pid == null)) {
+ if(null != pid) {
started(socket);
return true;
}
@@ -183,10 +130,12 @@ namespace Tmate
var args = new GenericArray<string>();
args.data = {"/usr/bin/tmate", "-F"};
- if(! (config == null) && FileUtils.test(config, IS_REGULAR)) {
+ if(null != config) {
+ this.config = config;
args.add("-f");
- args.add(config);
+ args.add(config.get_path());
}
+
try {
Process.spawn_async_with_pipes(
null, args.data, null,
@@ -202,29 +151,42 @@ namespace Tmate
try {
string line;
- MatchInfo info;
channel.read_line (out line, null, null);
- if(r_socket.match(line, 0, out info))
- socket = info.fetch(1);
- else if (r_connect.match(line) && socket != null)
- started(socket);
- else if(r_http.match(line, 0, out info))
- address_set(HTTP, info.fetch(1));
- else if(r_http_ro.match(line, 0, out info))
- address_set(HTTP_READONLY, info.fetch(1));
- else if(r_ssh.match(line, 0, out info))
- address_set(SSH, info.fetch(1));
- else if(r_ssh_ro.match(line, 0, out info))
- address_set(SSH_READONLY, info.fetch(1));
- else if(r_restarted.match(line))
+ Stdout.Token token = (new Stdout()).parse(line);
+ debug(token.to_string());
+
+ switch(token.class) {
+ case SOCKET:
+ socket = token.list[0];
+ return true;
+ case INIT:
+ started (socket);
+ delete_config();
+ return true;
+ case ADDRESS:
+ address_set(
+ SessionType.from_string(
+ token.list[0], token.list[1]
+ ), token.list[2]);
+ return true;
+ case RESTART:
restart();
- else if(r_closed.match(line))
+ return true;
+ case TERM:
+ info (_("Session terminated."));
stopped();
- else if(r_netfail.match(line, 0, out info))
- network_error(info.fetch(1));
- else if(r_note.match(line)) unlikely(false); // Ignore line
- else
- debug("Unprocessed line: \"%s\"", line);
+ return false;
+ case ERROR:
+ this.error(token.list[0], token.list[1]);
+ return true;
+ case COMMENT:
+ return true; // not needed.
+ case MATES:
+ return true;// TODO: handle mates join/leave
+ case UNKNOWN:
+ debug("%s", token.list[0]);
+ return true;
+ }
} catch (IOChannelError e) {
print ("IOChannelError: %s\n", e.message);
return false;
@@ -237,13 +199,15 @@ namespace Tmate
ChildWatch.add(pid, (pid, status) => {
Process.close_pid(pid);
- if(flags != DISCONNECTED)
- stopped();
+ reset();
+ stopped();
});
return true;
} catch (SpawnError e) {
warning("Error: %s", e.message);
+ this.error(e.message);
+ reset();
stopped();
return false;
}