Changeset 03426e0 in mod_gnutls


Ignore:
Timestamp:
Dec 2, 2019, 12:20:05 PM (11 months ago)
Author:
Fiona Klute <fiona.klute@…>
Branches:
master, proxy-ticket
Children:
fc8eefcd
Parents:
dec05c4
Message:

https-test-client.py: Prototype of output stream filter for gnutls-cli

The filter removes a log line about loading client certificates that
is mistakenly sent to stdout. My fix for gnutls-cli has been merged,
but buggy binaries will probably be around for a while.

See: https://gitlab.com/gnutls/gnutls/merge_requests/1125

File:
1 edited

Legend:

Unmodified
Added
Removed
  • test/https-test-client.py

    rdec05c4 r03426e0  
    1616# limitations under the License.
    1717
     18import select
    1819import socket
    1920import subprocess
     21import sys
     22import traceback
    2023import yaml
    2124
    2225from http.client import HTTPConnection
     26from multiprocessing import Process
    2327from time import sleep
    2428
     
    4044        # (see exception doc)
    4145        self.set_tunnel = None
     46        self._fproc = None
     47
     48    @classmethod
     49    def _filter(cls, in_stream, out_stream):
     50        import fcntl
     51        import os
     52        # This filters out a log line about loading client
     53        # certificates that is mistakenly sent to stdout. My fix has
     54        # been merged, but buggy binaries will probably be around for
     55        # a while.
     56        # https://gitlab.com/gnutls/gnutls/merge_requests/1125
     57        cert_log = b'Processed 1 client X.509 certificates...\n'
     58
     59        fd = in_stream.fileno()
     60        fl = fcntl.fcntl(fd, fcntl.F_GETFL)
     61        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
     62        poller = select.poll()
     63        poller.register(fd)
     64
     65        run_loop = True
     66        while run_loop:
     67            # Critical: "event" is a bitwise OR of the POLL* constants
     68            for x, event in poller.poll():
     69                print(f'fd {x}: {event}')
     70                if event & select.POLLIN or event & select.POLLPRI:
     71                    data = in_stream.read()
     72                    print(f'read {len(data)} bytes')
     73                    if cert_log in data:
     74                        data = data.replace(cert_log, b'')
     75                        print('skip')
     76                    out_stream.send(data)
     77                if event & select.POLLHUP or event & select.POLLRDHUP:
     78                    # Stop the loop, but process any other events that
     79                    # might be in the list returned by poll() first.
     80                    run_loop = False
     81                    print('received HUP')
     82                sys.stdout.flush()
     83
     84        print('filter process cleanin up')
     85        sys.stdout.flush()
     86
     87        in_stream.close()
     88        out_stream.close()
    4289
    4390    def connect(self):
     
    4794
    4895        # TODO: Maybe capture stderr?
    49         self._sproc = subprocess.Popen(self.command, stdout=s_remote,
    50                                        stdin=s_remote, close_fds=True)
     96        self._sproc = subprocess.Popen(self.command, stdout=subprocess.PIPE,
     97                                       stdin=s_remote, close_fds=True,
     98                                       bufsize=0)
     99        self._fproc = Process(target=HTTPSubprocessConnection._filter,
     100                              args=(self._sproc.stdout, s_remote))
     101        self._fproc.start()
    51102        s_remote.close()
    52103        self.sock = s_local
     104        print(f'socket created {self.sock}')
     105        sys.stdout.flush()
    53106
    54107    def close(self):
    55         super().close()
    56         # Wait for the process to stop, send SIGTERM/SIGKILL if
    57         # necessary
     108        traceback.print_stack()
     109        # Wait for the process to stop, send SIGKILL if necessary
     110        self._sproc.terminate()
    58111        self.returncode = self._sproc.wait(self.timeout)
    59112        if self.returncode == None:
    60             self._sproc.terminate()
     113            self._sproc.kill()
    61114            self.returncode = self._sproc.wait(self.timeout)
    62             if self.returncode == None:
    63                 self._sproc.kill()
    64                 self.returncode = self._sproc.wait(self.timeout)
     115
     116        # filter process receives HUP on socket when the subprocess
     117        # terminates
     118        self._fproc.join()
     119
     120        print(f'socket closing {self.sock}')
     121        super().close()
    65122
    66123
Note: See TracChangeset for help on using the changeset viewer.