diff options
author | Rob Austein <sra@hactrn.net> | 2010-04-29 23:18:20 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2010-04-29 23:18:20 +0000 |
commit | ece88ce635fe5edf1de019c23124b24f6c9a7f29 (patch) | |
tree | cf0a22db07d304baba1d20394317dc5f2966c078 /rtr-origin | |
parent | c19bd5639131a1bceb6d30f132bda3a115b805d4 (diff) |
Apparently sshd has a compile-time option that causes it to invoke
subsystem code with two unidirectional pipes rather than a single
bidirectional socketpair, in which case treating file descriptor zero
as a bidirectional socket doesn't work so well. Rewrite server mode
code to use a pair of unidirectional channels to compensate.
svn path=/rtr-origin/rtr-origin.py; revision=3228
Diffstat (limited to 'rtr-origin')
-rw-r--r-- | rtr-origin/rtr-origin.py | 91 |
1 files changed, 72 insertions, 19 deletions
diff --git a/rtr-origin/rtr-origin.py b/rtr-origin/rtr-origin.py index 12ecca24..ecb5bb67 100644 --- a/rtr-origin/rtr-origin.py +++ b/rtr-origin/rtr-origin.py @@ -720,6 +720,42 @@ class pdu_channel(asynchat.async_chat): log("Exiting after unhandled exception") asyncore.close_all() + def init_file_dispatcher(self, fd): + """ + Kludge to plug asyncore.file_dispatcher into asynchat. Call from + subclass's __init__() method, after calling + pdu_channel.__init__(), and don't read this on a full stomach. + """ + self.connected = True + self._fileno = fd + self.socket = asyncore.file_wrapper(fd) + self.add_channel() + flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0) + flags = flags | os.O_NONBLOCK + fcntl.fcntl(fd, fcntl.F_SETFL, flags) + +class server_write_channel(pdu_channel): + """ + Kludge to deal with ssh's habit of sometimes (compile time option) + invoking us with two unidirectional pipes instead of one + bidirectional socketpair. All the server logic is in the + server_channel class, this class just deals with sending the + server's output to a different file descriptor. + """ + + def __init__(self): + """ + Set up stdout. + """ + pdu_channel.__init__(self) + self.init_file_dispatcher(sys.stdout.fileno()) + + def readable(self): + """ + This channel is never readable. + """ + return False + class server_channel(pdu_channel): """ Server protocol engine, handles upcalls from pdu_channel to @@ -728,28 +764,45 @@ class server_channel(pdu_channel): def __init__(self): """ - Set up stdin as connection and start listening for first PDU. + Set up stdin and stdout as connection and start listening for + first PDU. """ pdu_channel.__init__(self) - # - # I don't know a sane way to get asynchat.async_chat.__init__() to - # call asyncore.file_dispatcher.__init__(), so shut your eyes for - # a moment while I cut and paste. - # - fd = sys.stdin.fileno() - self.connected = True - self._fileno = fd - self.socket = asyncore.file_wrapper(fd) - self.add_channel() - flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0) - flags = flags | os.O_NONBLOCK - fcntl.fcntl(fd, fcntl.F_SETFL, flags) - # - # Ok, you can look again now. - # + self.init_file_dispatcher(sys.stdin.fileno()) + self.writer = server_write_channel() self.get_serial() self.start_new_pdu() + def writable(self): + """ + This channel is never writable. + """ + return False + + def push(self, data): + """ + Redirect to writer channel. + """ + return self.writer.push(data) + + def push_with_producer(self, producer): + """ + Redirect to writer channel. + """ + return self.writer.push_with_producer(producer) + + def push_pdu(self, pdu): + """ + Redirect to writer channel. + """ + return self.writer.push_pdu(pdu) + + def push_file(self, f): + """ + Redirect to writer channel. + """ + return self.writer.push_file(f) + def deliver_pdu(self, pdu): """ Handle received PDU. @@ -872,10 +925,10 @@ class client_channel(pdu_channel): def handle_close(self): """ - Intercept close event so we can log it. + Intercept close event so we can log it, then shut down. """ log("Server closed channel") - asynchat.async_chat.handle_close(self) + rpki.async.exit_event_loop() class kickme_channel(asyncore.dispatcher): """ |