2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-05 00:55:24 +00:00
Files
bind/bin/tests/system/tcp/ans6/ans.py
Diego Fronza 29be224a04 Added TCP high-water system tests
Note: ans6/ans6.py is a helper script that allows tests.sh to open/close
TCP connections to some BIND instance.
2019-11-06 09:18:27 +01:00

154 lines
4.5 KiB
Python

############################################################################
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
############################################################################
############################################################################
#
# This tool allows an arbitrary number of TCP connections to be made to the
# specified service and to keep them open until told otherwise. It is
# controlled by writing text commands to a TCP socket (default port: 5309).
#
# Currently supported commands:
#
# - open <COUNT> <HOST> <PORT>
#
# Opens <COUNT> TCP connections to <HOST>:<PORT> and keeps them open.
# <HOST> must be an IP address (IPv4 or IPv6).
#
# - close <COUNT>
#
# Close the oldest <COUNT> previously established connections.
#
############################################################################
from __future__ import print_function
import datetime
import errno
import os
import select
import signal
import socket
import sys
import time
# Timeout for establishing all connections requested by a single 'open' command.
OPEN_TIMEOUT = 2
def log(msg):
print(datetime.datetime.now().strftime('%d-%b-%Y %H:%M:%S.%f ') + msg)
def open_connections(active_conns, count, host, port):
queued = []
errors = []
try:
socket.inet_aton(host)
family = socket.AF_INET
except socket.error:
family = socket.AF_INET6
log('Opening %d connections...' % count)
for _ in range(count):
sock = socket.socket(family, socket.SOCK_STREAM)
sock.setblocking(0)
err = sock.connect_ex((host, port))
if err not in (0, errno.EINPROGRESS):
log('%s on connect for socket %s' % (errno.errorcode[err], sock))
errors.append(sock)
else:
queued.append(sock)
start = time.time()
while queued:
now = time.time()
time_left = OPEN_TIMEOUT - (now - start)
if time_left <= 0:
break
_, wsocks, _ = select.select([], queued, [], time_left)
for sock in wsocks:
queued.remove(sock)
err = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
if err:
log('%s for socket %s' % (errno.errorcode[err], sock))
errors.append(sock)
else:
active_conns.append(sock)
if errors:
log('result=FAIL: %d connection(s) failed' % len(errors))
elif queued:
log('result=FAIL: Timed out, aborting %d pending connections' % len(queued))
for sock in queued:
sock.close()
else:
log('result=OK: Successfully opened %d connections' % count)
def close_connections(active_conns, count):
log('Closing %d connections...' % count)
for _ in range(count):
sock = active_conns.pop(0)
sock.close()
log('result=OK: Successfully closed %d connections' % count)
def sigterm(*_):
log('SIGTERM received, shutting down')
os.remove('ans.pid')
sys.exit(0)
def main():
active_conns = []
signal.signal(signal.SIGTERM, sigterm)
with open('ans.pid', 'w') as pidfile:
print(os.getpid(), file=pidfile)
listenip = '10.53.0.6'
try:
port = int(os.environ['CONTROLPORT'])
except KeyError:
port = 5309
log('Listening on %s:%d' % (listenip, port))
ctlsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ctlsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ctlsock.bind((listenip, port))
ctlsock.listen(1)
while True:
(clientsock, _) = ctlsock.accept()
log('Accepted control connection from %s' % clientsock)
cmdline = clientsock.recv(512).decode('ascii').strip()
if cmdline:
log('Received command: %s' % cmdline)
cmd = cmdline.split()
if cmd[0] == 'open':
count, host, port = cmd[1:]
open_connections(active_conns, int(count), host, int(port))
elif cmd[0] == 'close':
(count, ) = cmd[1:]
close_connections(active_conns, int(count))
else:
log('result=FAIL: Unknown command')
clientsock.close()
if __name__ == '__main__':
main()