|
@@ -6,8 +6,14 @@ namespace LibPeer.Protocols.Stp.Sessions {
|
|
|
|
|
|
public abstract class Session : Object {
|
|
public abstract class Session : Object {
|
|
|
|
|
|
|
|
+ public const int64 HEARTBEAT_INTERVAL = 60;
|
|
|
|
+ public const int64 HEARTBEAT_TIMEOUT = 330;
|
|
|
|
+
|
|
protected AsyncQueue<Segment> outgoing_segment_queue = new AsyncQueue<Segment>();
|
|
protected AsyncQueue<Segment> outgoing_segment_queue = new AsyncQueue<Segment>();
|
|
|
|
|
|
|
|
+ private int64 last_heartbeat = 0;
|
|
|
|
+ private Thread<bool> heart;
|
|
|
|
+
|
|
public bool open { get; protected set; }
|
|
public bool open { get; protected set; }
|
|
|
|
|
|
public signal void session_closed(string reason);
|
|
public signal void session_closed(string reason);
|
|
@@ -22,6 +28,9 @@ namespace LibPeer.Protocols.Stp.Sessions {
|
|
this.target = target;
|
|
this.target = target;
|
|
identifier = session_id;
|
|
identifier = session_id;
|
|
initial_ping = ping;
|
|
initial_ping = ping;
|
|
|
|
+ last_heartbeat = get_heartbeat_timestamp();
|
|
|
|
+
|
|
|
|
+ heart = new Thread<bool>("STP Session Heartbeat", heartbeat);
|
|
}
|
|
}
|
|
|
|
|
|
public virtual bool has_pending_segment() {
|
|
public virtual bool has_pending_segment() {
|
|
@@ -49,6 +58,24 @@ namespace LibPeer.Protocols.Stp.Sessions {
|
|
queue_segment(new Control(ControlCommand.COMPLETE));
|
|
queue_segment(new Control(ControlCommand.COMPLETE));
|
|
close_session("Stream closed by local application");
|
|
close_session("Stream closed by local application");
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ private bool heartbeat() {
|
|
|
|
+ while(open) {
|
|
|
|
+ Posix.sleep((uint)HEARTBEAT_INTERVAL);
|
|
|
|
+ if(get_heartbeat_timestamp() > last_heartbeat + HEARTBEAT_TIMEOUT ) {
|
|
|
|
+ queue_segment(new Control(ControlCommand.ABORT));
|
|
|
|
+ close_session("The remote peer died");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ queue_segment(new Control(ControlCommand.HEARTBEAT));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private int64 get_heartbeat_timestamp() {
|
|
|
|
+ return get_monotonic_time()/1000000;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|