mirror of
https://codeberg.org/JasterV/uni-lab.git
synced 2026-04-26 18:40:03 +00:00
187 lines
4.8 KiB
Python
Executable file
187 lines
4.8 KiB
Python
Executable file
import socket
|
|
import sys
|
|
import struct
|
|
import select
|
|
import time
|
|
import datetime
|
|
import threading
|
|
import signal
|
|
import os
|
|
|
|
|
|
# Paquets de la fase de registre
|
|
REG_REQ = 0x00
|
|
REG_INFO = 0x01
|
|
REG_ACK = 0x02
|
|
INFO_ACK = 0x03
|
|
REG_NACK = 0x04
|
|
INFO_NACK = 0x05
|
|
REG_REJ = 0x06
|
|
|
|
# Paquets per a la comunicació periòdica
|
|
ALIVE = 0x10
|
|
ALIVE_REJ = 0x11
|
|
|
|
# Paquets per a la transferència de dades amb el servidor
|
|
SEND_DATA = 0x20
|
|
SET_DATA = 0x21
|
|
GET_DATA = 0x22
|
|
DATA_ACK = 0x23
|
|
DATA_NACK = 0x24
|
|
DATA_REJ = 0x25
|
|
|
|
# Els possibles estats que pot tenir un client
|
|
DISCONNECTED = 0xa0
|
|
NOT_REGISTERED = 0xa1
|
|
WAIT_ACK_REG = 0xa2
|
|
WAIT_INFO = 0xa3
|
|
WAIT_ACK_INFO = 0xa4
|
|
REGISTERED = 0xa5
|
|
SEND_ALIVE = 0xa6
|
|
|
|
|
|
# Valors per a les proves de protocol de registre
|
|
t = 1.0
|
|
u = 2.0
|
|
n = 7.0
|
|
o = 3.0
|
|
p = 3.0
|
|
q = 3.0
|
|
v = 2.0
|
|
r = 2.0
|
|
s = 3.0
|
|
m = 3.0
|
|
|
|
# -----------------------------------
|
|
# ----------DEBUG UTILITIES----------
|
|
# -----------------------------------
|
|
|
|
|
|
class Logger:
|
|
def __init__(self):
|
|
self.debug_mode = False
|
|
|
|
def turn_debug_on(self):
|
|
self.debug_mode = True
|
|
|
|
def debug_print(self, message):
|
|
now = datetime.datetime.now()
|
|
if self.debug_mode:
|
|
print("{0}:{1}:{2} => {3}".format(
|
|
now.hour, now.minute, now.second, message))
|
|
|
|
def handler(signum, frame):
|
|
print('Procés acabat per ctrl+c')
|
|
sys.exit(0)
|
|
|
|
# --------------------------------------------
|
|
# -------------SOCKETS UTILITIES--------------
|
|
# --------------------------------------------
|
|
|
|
|
|
def unpack_response(fmt, response):
|
|
try:
|
|
t = struct.unpack(fmt, response)
|
|
return tuple(x if isinstance(x, int) else x.split(b'\x00')[0].decode() for x in t)
|
|
except:
|
|
# Considerem un error en el desenpaquetament si
|
|
# el servidor ens ha enviat un paquet mal format i
|
|
# retornem null
|
|
return None
|
|
|
|
|
|
def recvfrom(sock):
|
|
response, server_addr = sock.recvfrom(84)
|
|
return unpack_response('!B13s9s61s', response), server_addr
|
|
|
|
|
|
def sendto(sock, address, pack_type, client_id, rand_num, info):
|
|
data = struct.pack('!B13s9s61s', pack_type, client_id.encode(),
|
|
rand_num.encode(), info.encode())
|
|
sock.sendto(data, address)
|
|
|
|
|
|
def recv(sock):
|
|
response = sock.recv(127)
|
|
return unpack_response('!B13s9s8s16s80s', response)
|
|
|
|
|
|
def send(sock, pack_type, client_id, rand_num, elem_name, elem_value, info):
|
|
data = struct.pack('!B13s9s8s16s80s', pack_type, client_id.encode(), rand_num.encode(
|
|
), elem_name.encode(), elem_value.encode(), info.encode())
|
|
sock.send(data)
|
|
|
|
# -------------------------------------
|
|
# ------------CLIENT CLASS-------------
|
|
# -------------------------------------
|
|
|
|
|
|
class Client():
|
|
"""Representa l'estat d'un client amb la seva configuració
|
|
"""
|
|
|
|
def __init__(self, configfile):
|
|
config = read_cfg(configfile)
|
|
self.id = config['Id']
|
|
self.elems = config['Params']
|
|
self.local_tcp = config['Local-TCP']
|
|
self.server = config['Server']
|
|
self.server_udp = config['Server-UDP']
|
|
self.current_state = NOT_REGISTERED
|
|
self.register_attemps = 0
|
|
|
|
def has_state(self, *states):
|
|
for state in states:
|
|
if self.current_state == state:
|
|
return True
|
|
return False
|
|
|
|
def set_udp_communication_port(self, udp_port):
|
|
self.udp_port = udp_port
|
|
|
|
def set_tcp_communication_port(self, tcp_port):
|
|
self.tcp_port = tcp_port
|
|
|
|
def set_server_credentials(self, server_id, rand_num, server_ip):
|
|
self.server_id = server_id
|
|
self.rand_num = rand_num
|
|
self.server_ip = server_ip
|
|
|
|
def check_server_credentials(self, server_id=None, rand_num=None, server_ip=None):
|
|
if server_id is not None:
|
|
if server_id != self.server_id:
|
|
return False
|
|
if rand_num is not None:
|
|
if rand_num != self.rand_num:
|
|
return False
|
|
if server_ip is not None:
|
|
if server_ip != self.server_ip:
|
|
return False
|
|
return True
|
|
|
|
def local_address(self, port=0):
|
|
return ('', port)
|
|
|
|
|
|
def read_cfg(filename):
|
|
"""Llegeix el fitxer de configuració del client
|
|
i retorna un diccionari <String, dynamic> amb les dades llegides
|
|
"""
|
|
try:
|
|
cfg = open(filename)
|
|
config = dict()
|
|
for line in cfg:
|
|
items = line.strip().replace('=', ' ').split()
|
|
if len(items) == 2:
|
|
key, value = items
|
|
config[key] = value
|
|
t = config['Params'].strip().split(';')
|
|
config['Params'] = dict((key, "") for key in t)
|
|
config['Local-TCP'] = int(config['Local-TCP'])
|
|
config['Server-UDP'] = int(config['Server-UDP'])
|
|
config['Server'] = socket.gethostbyname(config['Server'])
|
|
return config
|
|
except FileNotFoundError:
|
|
print(
|
|
f"No s'ha trobat el fitxer {filename}")
|
|
sys.exit()
|