Skip to content

Commit

Permalink
UPD: add write methods, rename Device to Client
Browse files Browse the repository at this point in the history
  • Loading branch information
desty2k committed May 17, 2022
1 parent dd888ac commit e356f62
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 72 deletions.
20 changes: 17 additions & 3 deletions QtPyNetwork2/balancers/AbstractBalancer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from qtpy.QtCore import QObject, Signal, Slot
from abc import ABC, abstractmethod

import logging
from struct import calcsize
Expand All @@ -11,24 +12,37 @@ class AbstractBalancer(QObject):
disconnected = Signal(int)
connected = Signal(int, str, int)
message = Signal(int, bytes)
error = Signal(int, Exception)
client_error = Signal(int, Exception)
closed = Signal()

def __init__(self):
super(AbstractBalancer, self).__init__()
self.logger = logging.getLogger(self.__class__.__name__)
self.__socket_id = 0

@abstractmethod
@Slot(type, int)
def balance(self, socket_type: type, socket_descriptor: int):
pass

@abstractmethod
@Slot(int, bytes)
def write(self, device_id: int, message: bytes):
def write(self, client_id: int, message: bytes):
pass

@abstractmethod
@Slot(bytes)
def write_all(self, message: bytes):
pass

@abstractmethod
@Slot(int)
def close(self, device_id: int):
def disconnect(self, client_id: int):
pass

@abstractmethod
@Slot()
def close(self):
pass

@Slot()
Expand Down
68 changes: 58 additions & 10 deletions QtPyNetwork2/balancers/NoBalancer.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from qtpy.QtCore import Slot, Signal
from qtpy.QtNetwork import QAbstractSocket, QUdpSocket
from qtpy.QtNetwork import QAbstractSocket

from struct import unpack
from struct import unpack, pack

from .AbstractBalancer import AbstractBalancer
from .AbstractBalancer import AbstractBalancer, HEADER, HEADER_SIZE


class NoBalancer(AbstractBalancer):
Expand Down Expand Up @@ -67,9 +67,6 @@ def __on_socket_ready_read(self):
def __on_socket_disconnected(self):
"""Handle socket disconnection.
Args:
conn (QTcpSocket): Socket object.
Note:
Emits disconnected signal.
"""
Expand All @@ -87,14 +84,65 @@ def __on_socket_disconnected(self):
def __on_socket_error(self):
"""Handle socket errors.
Args:
conn (QTcpSocket): Socket object.
Note:
Emits error signal.
"""
socket = self.sender()
client_id = int(socket.objectName())
error = socket.errorString()
self.error.emit(client_id, Exception(error))
self.client_error.emit(client_id, Exception(error))

@Slot(int, bytes)
def write(self, client_id: int, data: bytes):
"""Write data to socket.
Args:
client_id (int): Client ID.
data (bytes): Data to write.
"""
for socket in self.sockets:
if int(socket.objectName()) == client_id:
data = pack(HEADER, len(data)) + data
socket.write(data)
socket.flush()
print(f"Written {len(data)} bytes to {socket.objectName()}")
return
print(f"{client_id} - {data}")
print([socket.objectName() for socket in self.sockets])
self.client_error.emit(client_id, Exception(f"Client {client_id} not found"))

@Slot(bytes)
def write_all(self, message: bytes):
"""Write data to all sockets.
Args:
message (bytes): Data to write.
"""
for socket in self.sockets:
socket.write(message)
socket.flush()

@Slot(int)
def disconnect(self, client_id: int):
"""Disconnect socket.
Args:
client_id (int): Client ID.
"""
for socket in self.sockets:
if int(socket.objectName()) == client_id:
socket.disconnectFromHost()
return
self.client_error.emit(client_id, Exception(f"Client {client_id} not found"))

@Slot()
def close(self):
"""Close all sockets."""
for socket in self.sockets:
try:
socket.disconnectFromHost()
socket.close()
except RuntimeError:
pass
self.sockets.clear()

128 changes: 74 additions & 54 deletions QtPyNetwork2/server/AbstractServer.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from qtpy.QtCore import Slot, Signal, QObject, QThread
from qtpy.QtNetwork import QTcpServer, QHostAddress

from QtPyNetwork.models import Device
from QtPyNetwork.exceptions import NotConnectedError, ServerNotRunning
from QtPyNetwork2.models import Client
from QtPyNetwork2.exceptions import NotConnectedError, ServerNotRunning

import logging

Expand All @@ -13,48 +13,49 @@ class AbstractServer(QObject):
started = Signal(str, int)
closed = Signal()

connected = Signal(Device, str, int)
disconnected = Signal(Device)
message = Signal(Device, bytes)
connected = Signal(Client, str, int)
disconnected = Signal(Client)
message = Signal(Client, bytes)

client_error = Signal(Device, Exception)
client_error = Signal(Client, Exception)
server_error = Signal(Exception)

def __init__(self, balancer: AbstractBalancer):
super(AbstractServer, self).__init__()
self.devices: list[Device] = []
self.clients: list[Client] = []
self.server: QObject = None
self.device_model = Device
self.client_model = Client

self.balancer = balancer
self.balancer.connected.connect(self.__on_balancer_device_connected)
self.balancer.message.connect(self.__on_balancer_device_message)
self.balancer.error.connect(self.__on_balancer_device_error)
self.balancer.connected.connect(self.__on_balancer_client_connected)
self.balancer.disconnected.connect(self.__on_balancer_client_disconnected)
self.balancer.message.connect(self.__on_balancer_client_message)
self.balancer.client_error.connect(self.__on_balancer_client_error)
self.balancer.closed.connect(self.on_closed)

@Slot(int, str, int)
def __on_balancer_device_connected(self, device_id: int, ip: str, port: int):
device = self.device_model(self, device_id, ip, port)
self.devices.append(device)
self.on_connected(device, ip, port)
def __on_balancer_client_connected(self, client_id: int, ip: str, port: int):
client = self.client_model(self, client_id, ip, port)
self.clients.append(client)
self.on_connected(client, ip, port)

@Slot(int, bytes)
def __on_balancer_device_message(self, device_id: int, message: bytes):
"""When server receives message from device."""
self.on_message(self.get_device_by_id(device_id), message)
def __on_balancer_client_message(self, client_id: int, message: bytes):
"""When server receives message from client."""
self.on_message(self.get_client_by_id(client_id), message)

@Slot(int)
def __on_balancer_device_disconnected(self, device_id: int):
"""When device disconnects from server."""
device = self.get_device_by_id(device_id)
device.set_connected(False)
if device in self.devices:
self.devices.remove(device)
self.on_disconnected(device)
def __on_balancer_client_disconnected(self, client_id: int):
"""When client disconnects from server."""
client = self.get_client_by_id(client_id)
client.set_connected(False)
if client in self.clients:
self.clients.remove(client)
self.on_disconnected(client)

@Slot(int, Exception)
def __on_balancer_device_error(self, device_id: int, error: Exception):
self.on_device_error(self.get_device_by_id(device_id), error)
def __on_balancer_client_error(self, client_id: int, error: Exception):
self.on_client_error(self.get_client_by_id(client_id), error)

@Slot(str, int)
def start(self, ip: str, port: int):
Expand All @@ -64,49 +65,49 @@ def start(self, ip: str, port: int):
def on_started(self, ip: str, port: int):
self.started.emit(ip, port)

@Slot(Device, str, int)
def on_connected(self, device: Device, ip: str, port: int):
@Slot(Client, str, int)
def on_connected(self, client: Client, ip: str, port: int):
"""Called when new client connects to server.
Emits connected signal.
Args:
device (Device): Device object.
client (Client): Client object.
ip (str): Client ip address.
port (int): Client port.
"""
self.connected.emit(device, ip, port)
self.connected.emit(client, ip, port)

@Slot(Device, bytes)
def on_message(self, device: Device, message: bytes):
@Slot(Client, bytes)
def on_message(self, client: Client, message: bytes):
"""Called when server receives message from client.
Emits message signal.
Args:
device (Device): Message sender.
client (Client): Message sender.
message (bytes): Message.
"""
self.message.emit(device, message)
self.message.emit(client, message)

@Slot(Device)
def on_disconnected(self, device: Device):
"""Called when device disconnects from server.
@Slot(Client)
def on_disconnected(self, client: Client):
"""Called when client disconnects from server.
Emits disconnected signal.
Args:
device (Device): Disconnected device.
client (Client): Disconnected client.
"""
self.disconnected.emit(device)
self.disconnected.emit(client)

@Slot(Device, Exception)
def on_device_error(self, device: Device, error: Exception):
@Slot(Client, Exception)
def on_client_error(self, client: Client, error: Exception):
"""Called when server error occurs.
Emits error signal.
Args:
device (Device): Device object.
client (Client): Client object.
error (Exception): Exception object.
"""
self.client_error.emit(device, error)
self.client_error.emit(client, error)

@Slot(Exception)
def on_server_error(self, error: Exception):
Expand All @@ -122,11 +123,30 @@ def on_server_error(self, error: Exception):
def on_closed(self):
self.closed.emit()

@Slot(Client, bytes)
def write(self, client: Client, message: bytes):
"""Sends message to client.
Args:
client (Client): Client object.
message (bytes): Message.
"""
self.balancer.write(client.id(), message)

@Slot(bytes)
def write_all(self, message: bytes):
"""Sends message to all clients.
Args:
message (bytes): Message.
"""
self.balancer.write_all(message)

@Slot(int)
def get_device_by_id(self, device_id: int):
for device in self.devices:
if device.id() == device_id:
return device
def get_client_by_id(self, client_id: int):
for client in self.clients:
if client.id() == client_id:
return client

@Slot()
def is_running(self) -> bool:
Expand Down Expand Up @@ -247,20 +267,20 @@ def close(self):
# @Slot(int, bytes)
# def __on_handler_device_message(self, device_id: int, message: bytes):
# """When server receives message from bot."""
# self.on_message(self.get_device_by_id(device_id), message)
# self.on_message(self.get_client_by_id(device_id), message)
#
# @Slot(int)
# def __on_handler_device_disconnected(self, device_id):
# """When bot disconnects from server."""
# device = self.get_device_by_id(device_id)
# device = self.get_client_by_id(device_id)
# device.set_connected(False)
# if device in self.__devices:
# self.__devices.remove(device)
# self.on_disconnected(device)
#
# @Slot(int, str)
# def __on_handler_device_error(self, device_id, error):
# self.on_error(self.get_device_by_id(device_id), error)
# self.on_error(self.get_client_by_id(device_id), error)
#
# @Slot(Device, str, int)
# def on_connected(self, device: Device, ip: str, port: int):
Expand Down Expand Up @@ -321,7 +341,7 @@ def close(self):
#
# @Slot(bytes)
# def write_all(self, data: bytes):
# """Write data to all devices."""
# """Write data to all clients."""
# if not self.__server or not self.__handler:
# raise ServerNotRunning("Server is not running")
# self.__handler.write_all.emit(data)
Expand Down Expand Up @@ -377,7 +397,7 @@ def close(self):
# return True
#
# @Slot(int)
# def get_device_by_id(self, device_id: int) -> Device:
# def get_client_by_id(self, device_id: int) -> Device:
# """Returns device with associated ID.
#
# Args:
Expand All @@ -389,7 +409,7 @@ def close(self):
# raise Exception("CLIENT-{} not found".format(device_id))
#
# def get_devices(self):
# """Returns list with devices."""
# """Returns list with clients."""
# return self.__devices
#
# def set_handler_class(self, handler):
Expand Down
6 changes: 5 additions & 1 deletion examples2/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def setup(self):
self.logger = logging.getLogger(self.__class__.__name__)

self.cln = QThreadedClient()
# self.cln.message.connect(self.client_data_received)
self.cln.message.connect(self.on_message)
self.cln.connected.connect(self.on_connected)
self.cln.failed_to_connect.connect(self.close)
self.cln.disconnected.connect(self.close)
Expand All @@ -30,6 +30,10 @@ def on_connected(self, ip: str, port: int):
self.logger.info(f"Connected to {ip}:{port}")
self.cln.write(b"Kick me plz")

@Slot(bytes)
def on_message(self, data: bytes):
self.logger.info(f"Received: {data}")

@Slot()
def close(self):
self.cln.close()
Expand Down
Loading

0 comments on commit e356f62

Please sign in to comment.