Improve address and connection handling
* improve address checking + add ipv6 capabilities Change-Id: I5369336bec449c27d79d857018f319266dfd4d0e Reviewed-on: https://forge.frm2.tum.de/review/c/secop/frappy/+/30885 Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de> Reviewed-by: Alexander Zaft <a.zaft@fz-juelich.de>
This commit is contained in:
@@ -21,22 +21,22 @@
|
||||
# *****************************************************************************
|
||||
"""provides tcp interface to the SECoP Server"""
|
||||
|
||||
import errno
|
||||
import os
|
||||
import socket
|
||||
import socketserver
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import errno
|
||||
import os
|
||||
|
||||
from frappy.datatypes import BoolType, StringType
|
||||
from frappy.errors import SECoPError
|
||||
from frappy.lib import formatException, \
|
||||
formatExtendedStack, formatExtendedTraceback
|
||||
from frappy.lib import formatException, formatExtendedStack, \
|
||||
formatExtendedTraceback
|
||||
from frappy.properties import Property
|
||||
from frappy.protocol.interface import decode_msg, encode_msg_frame, get_msg
|
||||
from frappy.protocol.messages import ERRORPREFIX, \
|
||||
HELPREPLY, HELPREQUEST, HelpMessage
|
||||
from frappy.protocol.messages import ERRORPREFIX, HELPREPLY, HELPREQUEST, \
|
||||
HelpMessage
|
||||
|
||||
DEF_PORT = 10767
|
||||
MESSAGE_READ_SIZE = 1024
|
||||
@@ -57,7 +57,7 @@ class TCPRequestHandler(socketserver.BaseRequestHandler):
|
||||
clientaddr = self.client_address
|
||||
serverobj = self.server
|
||||
|
||||
self.log.info("handling new connection from %s:%d" % clientaddr)
|
||||
self.log.info("handling new connection from %s", format_address(clientaddr))
|
||||
data = b''
|
||||
|
||||
# notify dispatcher of us
|
||||
@@ -160,7 +160,7 @@ class TCPRequestHandler(socketserver.BaseRequestHandler):
|
||||
|
||||
def finish(self):
|
||||
"""called when handle() terminates, i.e. the socket closed"""
|
||||
self.log.info('closing connection from %s:%d' % self.client_address)
|
||||
self.log.info('closing connection from %s', format_address(self.client_address))
|
||||
# notify dispatcher
|
||||
self.server.dispatcher.remove_connection(self)
|
||||
# close socket
|
||||
@@ -171,8 +171,28 @@ class TCPRequestHandler(socketserver.BaseRequestHandler):
|
||||
finally:
|
||||
self.request.close()
|
||||
|
||||
class DualStackTCPServer(socketserver.ThreadingTCPServer):
|
||||
"""Subclassed to provide IPv6 capabilities as socketserver only uses IPv4"""
|
||||
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True, enable_ipv6=False):
|
||||
super().__init__(
|
||||
server_address, RequestHandlerClass, bind_and_activate=False)
|
||||
|
||||
class TCPServer(socketserver.ThreadingTCPServer):
|
||||
# override default socket
|
||||
if enable_ipv6:
|
||||
self.address_family = socket.AF_INET6
|
||||
self.socket = socket.socket(self.address_family,
|
||||
self.socket_type)
|
||||
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
|
||||
if bind_and_activate:
|
||||
try:
|
||||
self.server_bind()
|
||||
self.server_activate()
|
||||
except:
|
||||
self.server_close()
|
||||
raise
|
||||
|
||||
|
||||
class TCPServer(DualStackTCPServer):
|
||||
daemon_threads = True
|
||||
# on windows, 'reuse_address' means that several servers might listen on
|
||||
# the same port, on the other hand, a port is not blocked after closing
|
||||
@@ -191,13 +211,16 @@ class TCPServer(socketserver.ThreadingTCPServer):
|
||||
self.name = name
|
||||
self.log = logger
|
||||
port = int(options.pop('uri').split('://', 1)[-1])
|
||||
enable_ipv6 = options.pop('ipv6', False)
|
||||
self.detailed_errors = options.pop('detailed_errors', False)
|
||||
|
||||
self.log.info("TCPServer %s binding to port %d", name, port)
|
||||
for ntry in range(5):
|
||||
try:
|
||||
socketserver.ThreadingTCPServer.__init__(
|
||||
self, ('0.0.0.0', port), TCPRequestHandler, bind_and_activate=True)
|
||||
DualStackTCPServer.__init__(
|
||||
self, ('', port), TCPRequestHandler,
|
||||
bind_and_activate=True, enable_ipv6=enable_ipv6
|
||||
)
|
||||
break
|
||||
except OSError as e:
|
||||
if e.args[0] == errno.EADDRINUSE: # address already in use
|
||||
@@ -217,3 +240,11 @@ class TCPServer(socketserver.ThreadingTCPServer):
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.server_close()
|
||||
|
||||
def format_address(addr):
|
||||
if len(addr) == 2:
|
||||
return '%s:%d' % addr
|
||||
address, port = addr[0:2]
|
||||
if address.startswith('::ffff'):
|
||||
return '%s:%d' % (address[7:], port)
|
||||
return '[%s]:%d' % (address, port)
|
||||
|
||||
Reference in New Issue
Block a user