119 lines
5.1 KiB
Python
Executable File
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()
|