nfv/nfv/nfv-common/nfv_common/tcp/_tcp_server.py

119 lines
5.1 KiB
Python
Executable File

#
# Copyright (c) 2015-2016 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
from nfv_common import debug
from nfv_common import selobj
from nfv_common.helpers import coroutine
from nfv_common.tcp._tcp_connection import TCPConnection
DLOG = debug.debug_get_logger('nfv_common.tcp')
class TCPServer(object):
"""
TCP Server
"""
def __init__(self, ip, port, msg_handler, max_connections=5, auth_key=None):
"""
Create a TCP Server
"""
self._auth_key = auth_key
self._connection = TCPConnection(ip, port)
self._socket = self._connection.sock
self._socket.listen(max_connections)
selobj.selobj_add_read_obj(self._connection.selobj, self.dispatch)
self._client_connections = dict()
self._message_handler = msg_handler
@coroutine
def selobj_error_callback(self):
while True:
select_obj = (yield)
client_connection = self._client_connections.get(select_obj, None)
if client_connection is not None:
selobj.selobj_del_read_obj(select_obj)
del self._client_connections[select_obj]
DLOG.info("Client connection error, from %s, port=%s."
% (client_connection.ip, client_connection.port))
selobj.selobj_del_error_callback(select_obj)
@coroutine
def dispatch(self):
while True:
select_obj = (yield)
if select_obj == self._connection.selobj:
# Client Connect
client_socket, client_address = self._socket.accept()
client_ip = client_address[0]
client_port = client_address[1]
client_connection = TCPConnection(client_ip, client_port,
client_socket, False, self,
self._auth_key)
selobj.selobj_add_read_obj(client_connection.selobj,
self.dispatch)
selobj.selobj_add_error_callback(client_connection.selobj,
self.selobj_error_callback)
self._client_connections[client_connection.selobj] \
= client_connection
DLOG.verbose("Client connected from %s, port=%s."
% (client_ip, client_port))
else:
# Client Data
client_connection = self._client_connections.get(select_obj,
None)
if client_connection is not None:
msg = client_connection.receive(blocking=False)
if msg is not None:
DLOG.verbose("Message received from %s, port=%s, "
"select_obj=%s." % (client_connection.ip,
client_connection.port,
select_obj))
self._message_handler(client_connection, msg)
client_connection = self._client_connections.get(select_obj,
None)
if client_connection is not None:
if client_connection.is_shutdown():
selobj.selobj_del_read_obj(select_obj)
selobj.selobj_del_error_callback(select_obj)
del self._client_connections[select_obj]
DLOG.verbose("Client connection closed, ip=%s, port=%s, "
"select_obj=%s." % (client_connection.ip,
client_connection.port,
select_obj))
else:
selobj.selobj_del_read_obj(select_obj)
selobj.selobj_del_error_callback(select_obj)
def closing_connection(self, select_obj):
"""
Connection is about to be closed
"""
client_connection = self._client_connections.get(select_obj, None)
if client_connection is not None:
selobj.selobj_del_read_obj(select_obj)
selobj.selobj_del_error_callback(select_obj)
del self._client_connections[select_obj]
DLOG.verbose("Client connection closing, ip=%s, port=%s, "
"select_obj=%s." % (client_connection.ip,
client_connection.port,
select_obj))
def shutdown(self):
"""
Shutdown the TCP Server
"""
connections = self._client_connections.copy()
for client_connection in connections.itervalues():
selobj.selobj_del_read_obj(client_connection.selobj)
selobj.selobj_del_error_callback(client_connection.selobj)
client_connection.close()
selobj.selobj_del_read_obj(self._connection.selobj)
self._connection.close()