c - libssh2: What to do with unsolicited data from the ssh server? -
i have program uses libssh2 administrate linux boxes. it's straightforward: connects linux boxes, downloads config file, keeps libssh2 connection open (and idle) if user presses buttons on gui can send appropriate shell commands linux boxes necessary.
it uses non-blocking i/o (via libssh2_session_set_blocking(session, 0)) network i/o can handled single thread without session a's activity being held off session b blocking on read or write, etc.
this works fine. because there strange problem occurs when program connected many (i.e. several dozen) boxes @ once. happens sessions connect usual, , config files downloaded successfully, , connections idle, expected. on few of sessions, few milliseconds after download completes (i.e. after i've libssh2_channel_read()'d config file bytes, , after libssh2_channel_close() has succeeded), additional bytes of data (usually 104 or 140) appear on session's tcp socket, ready read me , passed libssh2.
at point have problem, because (as far know) libssh2 session should idle, , don't know these unsolicited bytes of data. none of options satisfactory:
i ignore bytes, select() keeps waking because bytes there, causes thread spin , cpu usage rise long program open, that's not good.
i stop select()-ing on ready-for-read sockets data, can't tell if socket gets closed remote peer, , want able notify user when happens.
i recv() excess bytes , throw them away, apparently screws state of libssh2 connection's state machine because next time try use (e.g. when user wants me send ssh command machine) command not sent.
i sleep(1) or close connection , reconnect it, ugly work-arounds problem think should handled properly.
so questions are
what these strange unsolicited bytes?
what function should call pass them libssh2 make happy?
ps here examples of mystery received bytes looked like, obtained doing recv() msg_peek flag:
--- peek'd data session #1 (104 bytes): -------------------------------------------- 0000: ..#|)62.!.a..... [ab 1f 23 7c 29 36 32 e8 21 cf 41 91 88 de 06 a4] 0016: xc.??n.+ajls..di [78 63 f2 3f 3f 6e 16 2b 61 4a 4c 53 ab aa 64 69] 0032: ...d.]f.p...4;.3 [c2 d6 9e 64 b4 5d 66 db 50 ba 90 82 34 3b cc 33] 0048: co"..5..fr...yy. [63 4f 22 ba b1 35 9c 00 46 72 a6 9c bb 59 79 a1] 0064: ..l....._..1.>.k [d2 fe 4c 2e e4 81 eb fd 5f 8e f2 31 da 3e c0 4b] 0080: ...........(d... [1d af df 0d 0f d1 ef 1e 07 d1 9f 28 64 f4 07 d3] 0096: 0...sl.. [30 b6 ee f7 73 6c cd 85] --- peek'd data session #2 (104 bytes): ---------------------------------------------- 0000: g.5"....q....... [67 d9 35 22 85 90 ab eb 51 95 11 0c e6 ca 9f de] 0016: ...)... .6v&.lkf [ed 04 cb 29 e9 87 95 20 85 36 56 26 a9 6c 6b 46] 0032: ...m).v....js... [ce b2 d7 6d 29 bb 56 fc 8e 89 a2 4a 53 a9 02 19] 0048: .w1........ky... [a1 77 31 a1 fb f8 b7 94 ee e0 d3 6b 59 ea cc ae] 0064: ...~..[..vz..... [e3 e8 f2 7e 2e 89 5b c4 82 76 5a da ff b6 ae 91] 0080: ......7.0z..6g.j [8a cb c8 fc eb e1 37 8e 30 5a e5 b8 36 67 c7 4a] 0096: '...qjs. [27 da b8 8f 71 4a 53 ef] --- peek'd data session #3 (140 bytes): ------------------------------------------------- 0000: ...u.d.e..>a.... [04 c3 b1 75 e5 64 d1 45 9e b0 3e 61 81 e9 9b b7] 0016: ..\.....n..d..e. [e4 a2 5c b5 9e da a9 b9 6e 96 b7 44 12 bd 65 d9] 0032: .|(jp..,k.....r' [c0 7c 28 4a 70 15 90 2c 6b 01 02 1a e6 d1 72 27] 0048: ..%..r]e:...n.cu [0b 8c 25 eb cd 52 5d 45 3a c4 12 f2 4e 11 43 55] 0064: gix$...d:.m..ps1 [67 69 78 24 a1 e9 85 64 3a d5 6d 91 1a 50 73 31] 0080: z.]...8#...q..aw [5a ca 5d db 1d 1d 38 23 0e 05 99 71 98 d8 41 57] 0096: ..]....u.7...j.? [ee 86 5d d1 0c b8 ce 55 f6 37 b5 1c 0f 4a b2 3f] 0112: ...10.......h(.* [17 15 ee 31 30 ea ee e0 b9 07 d1 c9 68 28 83 2a] 0128: ....>..g9... [be c2 e4 f9 3e e2 ea 67 39 0f b2 8c]
closing ssh channel involves more steps "closing it" on 1 side.
first, documentation libssh2_channel_close()
says sends "an ssh_msg_close packet remote host serves instruction no further data sent it", ok, "the remote host may still send data until sends own close message in response".
this command should therefore followed libssh2_channel_wait_closed()
, handles rest of communication "until remote host closes named channel".
additionally, described e.g. in comment this libssh2 commit, "sending ssh_msg_channel_close without channel eof explicitly allowed in rfc 4254, non-conforming servers hang or time out when channel closed before eof".
thus performing combo of libssh2_channel_send_eof()
, libssh2_channel_wait_eof()
before close operation might necessary compatibility.
since libssh2 version 1.2.5 (april 13 2010), because of that commit mentioned earlier, libssh2 should send eof automatically when closing if not sent.
there examples in libssh2 (like scp_write.c) closure explicitly , looks this:
libssh2_channel_send_eof(channel); libssh2_channel_wait_eof(channel); libssh2_channel_wait_closed(channel); libssh2_channel_free(channel);
(of course, of functions above need invoked multiple times long return libssh2_error_eagain
non-blocking sockets.)
Comments
Post a Comment