summaryrefslogtreecommitdiffstats
path: root/examples/tests/ngtcp2test/server.py
diff options
context:
space:
mode:
Diffstat (limited to 'examples/tests/ngtcp2test/server.py')
-rw-r--r--examples/tests/ngtcp2test/server.py137
1 files changed, 137 insertions, 0 deletions
diff --git a/examples/tests/ngtcp2test/server.py b/examples/tests/ngtcp2test/server.py
new file mode 100644
index 0000000..9f4e9a0
--- /dev/null
+++ b/examples/tests/ngtcp2test/server.py
@@ -0,0 +1,137 @@
+import logging
+import os
+import re
+import subprocess
+import time
+from datetime import datetime, timedelta
+from threading import Thread
+
+from .tls import HandShake
+from .env import Env, CryptoLib
+from .log import LogFile, HexDumpScanner
+
+
+log = logging.getLogger(__name__)
+
+
+class ServerRun:
+
+ def __init__(self, env: Env, logfile: LogFile):
+ self.env = env
+ self._logfile = logfile
+ self.log_lines = self._logfile.get_recent()
+ self._data_recs = None
+ self._hs_recs = None
+ if self.env.verbose > 1:
+ log.debug(f'read {len(self.log_lines)} lines from {logfile.path}')
+
+ @property
+ def handshake(self):
+ if self._data_recs is None:
+ self._data_recs = [data for data in HexDumpScanner(source=self.log_lines)]
+ if self.env.verbose > 1:
+ log.debug(f'detected {len(self._data_recs)} hexdumps '
+ f'in {self._logfile.path}')
+ if self._hs_recs is None:
+ self._hs_recs = [hrec for hrec in HandShake(source=self._data_recs,
+ verbose=self.env.verbose)]
+ if self.env.verbose > 1:
+ log.debug(f'detected {len(self._hs_recs)} crypto records '
+ f'in {self._logfile.path}')
+ return self._hs_recs
+
+ @property
+ def hs_stripe(self):
+ return ":".join([hrec.name for hrec in self.handshake])
+
+
+def monitor_proc(env: Env, proc):
+ _env = env
+ proc.wait()
+
+
+class ExampleServer:
+
+ def __init__(self, env: Env, crypto_lib: str, verify_client=False):
+ self.env = env
+ self._crypto_lib = crypto_lib
+ self._path = env.server_path(self._crypto_lib)
+ self._logpath = f'{self.env.gen_dir}/{self._crypto_lib}-server.log'
+ self._log = LogFile(path=self._logpath)
+ self._logfile = None
+ self._process = None
+ self._verify_client = verify_client
+
+ @property
+ def path(self):
+ return self._path
+
+ @property
+ def crypto_lib(self):
+ return self._crypto_lib
+
+ @property
+ def uses_cipher_config(self):
+ return CryptoLib.uses_cipher_config(self.crypto_lib)
+
+ def supports_cipher(self, cipher):
+ return CryptoLib.supports_cipher(self.crypto_lib, cipher)
+
+ @property
+ def log(self):
+ return self._log
+
+ def exists(self):
+ return os.path.isfile(self.path)
+
+ def start(self):
+ if self._process is not None:
+ return False
+ creds = self.env.get_server_credentials()
+ assert creds
+ args = [
+ self.path,
+ f'--htdocs={self.env.htdocs_dir}',
+ ]
+ if self._verify_client:
+ args.append('--verify-client')
+ args.extend([
+ '*', str(self.env.examples_port),
+ creds.pkey_file, creds.cert_file
+ ])
+ self._logfile = open(self._logpath, 'w')
+ self._process = subprocess.Popen(args=args, text=True,
+ stdout=self._logfile, stderr=self._logfile)
+ t = Thread(target=monitor_proc, daemon=True, args=(self.env, self._process))
+ t.start()
+ timeout = 5
+ end = datetime.now() + timedelta(seconds=timeout)
+ while True:
+ if self._process.poll():
+ return False
+ try:
+ if self.log.scan_recent(pattern=re.compile(r'^Using document root'), timeout=0.5):
+ break
+ except TimeoutError:
+ pass
+ if datetime.now() > end:
+ raise TimeoutError(f"pattern not found in error log after {timeout} seconds")
+ self.log.advance()
+ return True
+
+ def stop(self):
+ if self._process:
+ self._process.terminate()
+ self._process = None
+ if self._logfile:
+ self._logfile.close()
+ self._logfile = None
+ return True
+
+ def restart(self):
+ self.stop()
+ self._log.reset()
+ return self.start()
+
+ def get_run(self) -> ServerRun:
+ return ServerRun(env=self.env, logfile=self.log)