diff --git a/Messanger/.idea/workspace.xml b/Messanger/.idea/workspace.xml
index f31c5ca..04d368e 100644
--- a/Messanger/.idea/workspace.xml
+++ b/Messanger/.idea/workspace.xml
@@ -10,12 +10,24 @@
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -25,11 +37,24 @@
-
+
+
+ get_response_msg
+
+
+
+
+
+
-
-
-
+
+
+
@@ -43,6 +68,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -50,6 +85,14 @@
+
+
+
+
+
+
+
+
@@ -101,26 +144,48 @@
-
+
+
-
+
-
-
-
-
+
+
+
+
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -128,7 +193,7 @@
-
+
@@ -136,5 +201,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Messanger/client/__main__.py b/Messanger/client/__main__.py
index 1ba45ed..a395735 100644
--- a/Messanger/client/__main__.py
+++ b/Messanger/client/__main__.py
@@ -4,21 +4,81 @@
import logging
import jim
import settings
+import dis
+
+class ClientVerifier(type):
+
+ def __init__(self, clsname, bases, clsdict):
+ self.verify_class(clsname, clsdict)
+ type.__init__(self, clsname, bases, clsdict)
+
+ def verify_class(self, clsname, clsdict):
+
+ socket_argval = None
+ for key, value in clsdict.items():
+ assert not isinstance(value, socket.socket), 'Creating socket in class level is forbidden'
+
+ instructions_list = dis.get_instructions(value)
+ for instruction in instructions_list:
+ if instruction.argval == 'socket' and instruction.opname == 'LOAD_GLOBAL':
+ while instruction.opname != 'STORE_ATTR':
+ instruction = next(instructions_list)
+ if instruction.opname == 'LOAD_ATTR' and instruction.arg == 2:
+ assert instruction.argval == 'SOCK_STREAM', 'Only SOCK_STREAM sockets is available'
+ socket_argval = instruction.argval
+
+ if socket_argval:
+ for key, value in clsdict.items():
+ forbidden_procs = ['listen', 'accept']
+ instructions_list = dis.get_instructions(value)
+ for instruction in instructions_list:
+ if instruction.argval == socket_argval:
+ next_instruction = next(instructions_list)
+ assert not (next_instruction.argval in forbidden_procs and
+ next_instruction.opname == 'LOAD_ATTR'), \
+ f"{clsname} have forbidden method {next_instruction.argval}"
+
+
+class Client(metaclass=ClientVerifier):
+ def __init__(self, host, port):
+ self.host = host
+ self.port = port
+ self.sock = None
+
+ def make_connection(self):
+ self.sock = socket.socket()
+ self.sock.connect((self.host, self.port))
+ logger.info(f'Client started with {self.host}:{self.port}')
+ print(f'Client started with {self.host}:{self.port}')
+
+ def get_presence_msg(self, action, data):
+ time = datetime.datetime.now()
+ msg = {
+ "action": action,
+ "time": time.isoformat(),
+ "user": {
+ "account_name": "anonim",
+ "status": "Yep, I am here!"
+ },
+ "data": data
+ }
+
+ return jim.pack(msg)
+
+ def send_request(self):
+ while True:
+ action = input('Enter action to send:')
+ data = input('Enter data to send:')
+ msg = self.get_presence_msg(action, data)
+ self.sock.sendall(msg)
-def get_presence_msg(action, data):
- time = datetime.datetime.now()
- msg = {
- "action": action,
- "time": time.isoformat(),
- "user": {
- "account_name": "anonim",
- "status": "Yep, I am here!"
- },
- "data": data
- }
-
- return jim.pack(msg)
+ def recv_response(self):
+ while True:
+ response = self.sock.recv(settings.BUFFERSIZE)
+ response = jim.unpack(response)
+ logger.info(f'Got next response from server: {response}')
+ print(f'Got next response from server: {response}')
host = getattr(settings, 'HOST', '127.0.0.1')
@@ -47,24 +107,14 @@ def get_presence_msg(action, data):
logger.addHandler(handler)
try:
- sock = socket.socket()
- sock.connect((host, port))
- logger.info(f'Client started with {host}:{port}')
- print(f'Client started with {host}:{port}')
- if args.mode == 'w':
- while True:
- action = input('Enter action to send:')
- data = input('Enter data to send:')
+ clientObj = Client(host, port)
+ clientObj.make_connection()
- msg = get_presence_msg(action, data)
- sock.sendall(msg)
+ if args.mode == 'w':
+ clientObj.send_request()
else:
- while True:
- response = sock.recv(settings.BUFFERSIZE)
- response = jim.unpack(response)
- logger.info(f'Got next response from server: {response}')
- print(f'Got next response from server: {response}')
+ clientObj.recv_response()
except KeyboardInterrupt:
logger.info('Client closed')
diff --git a/Messanger/server/__main__.py b/Messanger/server/__main__.py
index cb6fbca..7898538 100644
--- a/Messanger/server/__main__.py
+++ b/Messanger/server/__main__.py
@@ -6,6 +6,7 @@
import threading
import jim
import settings
+import dis
from routes import resolve, get_server_routes
from protocol import (
validate_request, make_response,
@@ -14,66 +15,83 @@
from handlers import handle_request
+class ServerVerifier(type):
-def get_response_msg():
- msg = {
- "response": 200,
- "alert": "Необязательное сообщение/уведомление"
- }
- return jim.pack(msg)
+ def __init__(self, clsname, bases, clsdict):
+ self.verify_class(clsname, clsdict)
+ type.__init__(self, clsname, bases, clsdict)
+ def verify_class(self, clsname, clsdict):
-def read_client_data(client, requests, buffersize):
- b_request = client.recv(buffersize)
- requests.append(b_request)
+ socket_argval = None
+ for key, value in clsdict.items():
+ assert not isinstance(value, socket.socket), 'Creating socket in class level is forbidden'
+ instructions_list = dis.get_instructions(value)
+ for instruction in instructions_list:
+ if instruction.argval == 'socket' and instruction.opname == 'LOAD_GLOBAL':
+ while instruction.opname != 'STORE_ATTR':
+ instruction = next(instructions_list)
+ if instruction.opname == 'LOAD_ATTR' and instruction.arg == 2:
+ assert instruction.argval == 'SOCK_STREAM', 'Only SOCK_STREAM sockets is available'
+ socket_argval = instruction.argval
-def write_client_data(client, response):
- client.send(response)
+ if socket_argval:
+ for key, value in clsdict.items():
+ forbidden_procs = ['connect']
+ instructions_list = dis.get_instructions(value)
+ for instruction in instructions_list:
+ if instruction.argval == socket_argval:
+ next_instruction = next(instructions_list)
+ assert not (next_instruction.argval in forbidden_procs and
+ next_instruction.opname == 'LOAD_ATTR'), \
+ f"{clsname} has forbidden method {next_instruction.argval}"
-host = getattr(settings, 'HOST', '127.0.0.1')
-port = getattr(settings, 'PORT', 7777)
+class PortDescriptor:
-parser = ArgumentParser()
-parser.add_argument('-a', '--addr', type=str, help='Sets ip address')
-parser.add_argument('-p', '--port', type=int, help='Sets port')
+ def __init__(self):
+ self._value = 7777
-args = parser.parse_args()
+ def __get__(self, instance, instance_type):
+ return self._value
-if args.addr:
- host = args.addr
-if args.port:
- port = args.port
+ def __set__(self, instance, value):
+ if type(value) is not int:
+ raise TypeError('Value must be integer')
+ if not value >= 0:
+ raise ValueError('Port number must be => 0')
+ self._value = value
-handler = logging.FileHandler('main.log', encoding=settings.ENCODING)
-error_handler = logging.FileHandler('error.log', encoding=settings.ENCODING)
-logging.basicConfig(
- level=logging.DEBUG,
- format='%(asctime)s - %(levelname)s - %(message)s',
- handlers=[
- handler,
- error_handler,
- logging.StreamHandler(),
- ]
-)
+class Server(metaclass=ServerVerifier):
+ def __init__(self, host, port):
+ self.host = host
+ self.port = PortDescriptor()
+ self.port = port
+ self.sock = None
+ def make_listen(self):
+ self.sock = socket.socket()
+ self.sock.bind((self.host, self.port))
+ self.sock.settimeout(0)
+ self.sock.listen(5)
+ logging.info(f'Server started with {self.host}:{self.port}')
-def main():
+ def read_client_data(self, client, requests, buffersize):
+ b_request = client.recv(buffersize)
+ requests.append(b_request)
- requests = []
- connections = []
+ def write_client_data(self, client, response):
+ client.send(response)
+
+ def run_event_loop(self):
+ requests = []
+ connections = []
- try:
- sock = socket.socket()
- sock.bind((host, port))
- sock.settimeout(0)
- sock.listen(5)
- logging.info(f'Server started with {host}:{port}')
while True:
try:
- client, address = sock.accept()
+ client, address = self.sock.accept()
logging.info(f'Client detected {address}')
connections.append(client)
except Exception:
@@ -86,7 +104,7 @@ def main():
for r_client in rlist:
thread = threading.Thread(
- target=read_client_data,
+ target=self.read_client_data,
args=(r_client, requests, settings.BUFFERSIZE)
)
thread.start()
@@ -97,11 +115,47 @@ def main():
for w_client in wlist:
thread = threading.Thread(
- target=write_client_data,
+ target=self.write_client_data,
args=(w_client, b_response)
)
thread.start()
+
+
+host = getattr(settings, 'HOST', '127.0.0.1')
+port = getattr(settings, 'PORT', 7777)
+
+parser = ArgumentParser()
+parser.add_argument('-a', '--addr', type=str, help='Sets ip address')
+parser.add_argument('-p', '--port', type=int, help='Sets port')
+
+args = parser.parse_args()
+
+if args.addr:
+ host = args.addr
+if args.port:
+ port = args.port
+
+handler = logging.FileHandler('main.log', encoding=settings.ENCODING)
+error_handler = logging.FileHandler('error.log', encoding=settings.ENCODING)
+
+logging.basicConfig(
+ level=logging.DEBUG,
+ format='%(asctime)s - %(levelname)s - %(message)s',
+ handlers=[
+ handler,
+ error_handler,
+ logging.StreamHandler(),
+ ]
+)
+
+
+def main():
+
+ serverObj = Server(host, port)
+ try:
+ serverObj.make_listen()
+ serverObj.run_event_loop()
except KeyboardInterrupt:
logging.info('Server closed')