Skip to content

Commit 95e469c

Browse files
authored
Add Server.close, fix close message semantics (#79)
When receiving a SSH_MSG_CHANNEL_CLOSE message you are supposed to send back a SSH_MSG_CHANNEL_CLOSE **unless** you already sent one.
1 parent 501ec75 commit 95e469c

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

lib/client.ml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -477,10 +477,15 @@ let input_msg t msg now =
477477
let* c = guard_some (Channel.lookup id t.channels) "no such channel" in
478478
let channels = Channel.remove (Channel.id c) t.channels in
479479
let msg = "all the channels are closed now, nothing left to do here" in
480-
Ok ({ t with channels },
480+
let msgs =
481+
match c.state with
482+
| Open ->
481483
[ Msg_channel_close (Channel.id c) ;
482-
Msg_disconnect (DISCONNECT_BY_APPLICATION, msg, "") ],
483-
[ `Disconnected ])
484+
Msg_disconnect (DISCONNECT_BY_APPLICATION, msg, "") ]
485+
| Sent_close ->
486+
[ Msg_disconnect (DISCONNECT_BY_APPLICATION, msg, "") ]
487+
in
488+
Ok ({ t with channels }, msgs, [ `Disconnected ])
484489
| _, Msg_disconnect (code, msg, lang) ->
485490
Log.err (fun m -> m "disconnected: %s %s%s"
486491
(Ssh.disconnect_code_to_string code)
@@ -541,7 +546,10 @@ let close ?(id = 0l) t =
541546
let* () = guard (established t) "not yet established" in
542547
let* c = guard_some (Channel.lookup id t.channels) "no such channel" in
543548
let msg = Ssh.Msg_channel_close c.them.id in
544-
Ok (output_msg t msg)
549+
let t, msg = output_msg t msg in
550+
let c = { c with state = Sent_close } in
551+
let t = { t with channels = Channel.update c t.channels } in
552+
Ok (t, msg)
545553
with
546554
| Error _ -> t, None
547555
| Ok (t, msg) -> t, Some msg

lib/server.ml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,9 @@ let input_msg t msg now =
552552
| Msg_channel_close recp_channel ->
553553
let open Channel in
554554
(match lookup recp_channel t.channels with
555-
| None -> make_noreply t (* XXX or should we disconnect ? *)
555+
| None ->
556+
Log.warn (fun m -> m "Unexpected SSH_MSG_CHANNEL_CLOSE %lu" recp_channel);
557+
make_noreply t (* XXX or should we disconnect ? *)
556558
| Some c ->
557559
let t = { t with channels = remove recp_channel t.channels } in
558560
(match c.state with
@@ -602,3 +604,16 @@ let output_channel_data t id data =
602604
let* c = guard_some (Channel.lookup id t.channels) "no such channel" in
603605
let* c, frags = Channel.output_data ~flush:false c data in
604606
Ok ({ t with channels = Channel.update c t.channels }, frags)
607+
608+
let close t id =
609+
match
610+
let* c = guard_some (Channel.lookup id t.channels) "no such channel" in
611+
let msg = Ssh.Msg_channel_close c.them.id in
612+
(* XXX: when can [output_msg] fail? what do we do then? *)
613+
let* t, msg = output_msg t msg in
614+
let c = { c with state = Sent_close } in
615+
let t = { t with channels = Channel.update c t.channels } in
616+
Ok (t, msg)
617+
with
618+
| Error _ -> t, None
619+
| Ok (t, msg) -> t, Some msg

0 commit comments

Comments
 (0)