async def handler(self, websocket, path): remoteIP, remotePort = websocket.remote_address remoteHost = str(remoteIP) + ':' + str(remotePort) peer = Peer(websocket, remoteHost, self.__callbackWrapper, self.connectionHandler, self.settings, self.TAG) try: while peer.run: message = await asyncio.wait_for( websocket.recv(), timeout=self.settings.TIMEOUT_SECONDS) if peer.run: asyncio.Task(peer.send_response(message)) else: break except asyncio.TimeoutError: logger.log_error(('TImeout: client {0}, peer {1}'.format( peer.client_id, peer.id)), self.TAG) finally: if peer.client_id != None: if peer.run: await self.connectionHandler.disconnect_client( peer.client_id) logger.log_info(('Conn closed: client {0}, peer {1}'.format( peer.client_id, peer.id)), self.TAG) else: logger.log_info(('Conn closed: peer {0}'.format(peer.id)), self.TAG) try: websocket.close() except: pass return
def __parse_settings(self): # self.__settings = ServerSettings() settings = {} default = False if self.__configFile is None or len(self.__configFile) == 0: self.__configFile = os.path.join(root_path, 'core', 'default.conf') default = True with open(self.__configFile) as fin: for line in fin: if not str(line).startswith('#'): configStrs = line.split('=', 1) if len(configStrs) == 2: key = configStrs[0].strip() value = str(configStrs[1]).strip('\n').strip() try: value = int(value) except: value = str(value).replace('"','').replace("'","") settings[key] = value self.__settings = ServerSettings(settings) # create the JMQT logger (get_logger function returns this logger) logger.set_logger(self.__settings.LOG_PATH, mode = self.__settings.LOG_MODE) if default: logger.log_info('No config file passed, falling back to default config "' + self.__configFile + '"') else: logger.log_info('Loading config "' + self.__configFile + '"')
def start(self): logger.log_info( ('Listening on tcp {0}'.format(self.settings.WEBSOCKET_PORT)), self.TAG) self.server = self.loop.run_until_complete( websockets.serve(self.handler, '0.0.0.0', self.settings.WEBSOCKET_PORT))
async def disconnect(self): self.run = False self.writer.close() if self.client_id != None: logger.log_info(('Conn closed: client {0}, peer {1}'.format( self.client_id, self.id)), self.tag) else: logger.log_info(('Conn closed: peer {0}'.format(self.id)), self.tag)
def start(self): logger.log_info( ('Listening on tcp {0}'.format(self.settings.SOCKET_PORT)), self.TAG) self.coro = asyncio.start_server(self.handle_client, '', self.settings.SOCKET_PORT, loop=self.loop) self.server = self.loop.run_until_complete(self.coro)
def connect_sqlite(self): root_path = os.path.dirname(os.path.realpath(__file__)) db_path = os.path.join(root_path, 'jmqt.db') logger.log_info('Connecting SQLite Db ' + db_path, 'SQLiteService') db = SqliteDatabase(db_path) DB_PROXY.initialize(db) db.connect() db.create_tables( [Connections, Subscriptions, RetainedPackets, Packets, Pubmaps], safe=True)
def start(self): logger.log_info( ('Listening on tcp {0}'.format(self.settings.SSL_WEBSOCKET_PORT)), self.TAG) sc = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) sc.load_cert_chain(self.settings.SSL_CERT_PATH, self.settings.SSL_KEY_PATH) self.server = self.loop.run_until_complete( websockets.serve(self.handler, '0.0.0.0', self.settings.SSL_WEBSOCKET_PORT, ssl=sc))
def start(self): logger.log_info( ('Listening on tcp {0}'.format(self.settings.SSL_SOCKET_PORT)), self.TAG) sc = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) sc.load_cert_chain(self.settings.SSL_CERT_PATH, self.settings.SSL_KEY_PATH) self.coro = asyncio.start_server(self.handle_client, '', self.settings.SSL_SOCKET_PORT, ssl=sc, loop=self.loop) self.server = self.loop.run_until_complete(self.coro)
def connect_mysql(self): logger.log_info(('Connecting MySQL/MariaDb {0} on {1}:{2}').format( self.settings.MYSQL_DB, self.settings.MYSQL_HOST, self.settings.MYSQL_PORT), 'MySQLService') db = MySQLDatabase(self.settings.MYSQL_DB, user=self.settings.MYSQL_USER, password=self.settings.MYSQL_PSWD, host=self.settings.MYSQL_HOST, port=self.settings.MYSQL_PORT) DB_PROXY.initialize(db) db.connect() db.create_tables( [Connections, Subscriptions, RetainedPackets, Packets, Pubmaps])
def __init__(self, settings, eventLoop): self.server_id = str(uuid.uuid4()) self.settings = settings self.loop = eventLoop self.peers = {} self.pubmap = {} if not self.settings.ENABLE_MYSQL and self.settings.ENABLE_REDIS: logger.log_warning("MySQL/MariaDb is disbled, but Redis is enabled. Distributed system won't work without MySQL/MariaDb", 'ConnectionHandler') if self.settings.ENABLE_MYSQL: logger.log_info('MySQL/MariaDb is enabled. Initiating MySQL/MariaDb..', 'ConnectionHandler') from pyjmqt.server.core.services.dbservice import MySQLService self.dbService = MySQLService(self.settings) else: logger.log_info('MySQL/MariaDb is disabled. Switching to SQLite..', 'ConnectionHandler') from pyjmqt.server.core.services.dbservice import SQLiteService self.dbService = SQLiteService(self.settings) self.cacheService = CacheService(self.settings, self.loop, self.server_id, self.dbService, self.__process_pub, self.disconnect_client)
async def create_response(self, packet, peer): response = None data = {} if (packet != None): #auth handler if packet.packetType == PacketTypes.auth: auth_data = PacketParser.get_arg(JSONKeys.data, packet.packetData) status_code, client_id, auth_token, message = await peer.callbackWrapper.validate_auth_callback(auth_data, peer.address, packet.protocol) if status_code != StatusCode.OK: log_msg = ('Auth FAILED: auth Data {1}, message {0} [{2}]').format(message, auth_data, peer.id) logger.log_warning(log_msg, peer.tag) response = PacketGenerator.generate_auth_res(status_code, client_id, auth_token, message) #conn handler elif packet.packetType == PacketTypes.conn: auth_token = PacketParser.get_arg(JSONKeys.authToken, packet.packetData) client_id = PacketParser.get_arg(JSONKeys.clientId, packet.packetData) status_code = await peer.callbackWrapper.validate_conn_callback(client_id, auth_token, peer.address, packet.protocol) if status_code == StatusCode.OK: connected = await self.connect_client(auth_token, client_id, packet.protocol, peer) if connected: status_code = StatusCode.OK data = {'client_id' : client_id} info_msg = ('Connnected: client {0} {1}').format(client_id, peer.id) logger.log_info(info_msg, peer.tag) else: status_code = StatusCode.NOT_ALLOWED if status_code != StatusCode.OK: log_msg = ('Conn FAILED: token {1}, status {0} {2}').format(status_code, auth_token, peer.id) logger.log_warning(log_msg, peer.tag) response = PacketGenerator.generate_conn_res(status_code, self.settings.TIMEOUT_SECONDS) elif peer.client_id != None: #disconn handler if packet.packetType == PacketTypes.disconn: pck_id = PacketParser.get_arg(JSONKeys.packetId, packet.packetData) await self.disconnect_client(peer.client_id, has_client_disconnected = True) log_msg = ('disconn from client {0} {1}').format(peer.client_id, peer.id) logger.log_info(log_msg, peer.tag) #pub handler elif packet.packetType == PacketTypes.pub: channel_name = PacketParser.get_arg(JSONKeys.channelName, packet.packetData) channel_valid, channel_name = self.is_channel_valid(channel_name) pck_id = PacketParser.get_arg(JSONKeys.packetId, packet.packetData) if channel_valid: data = PacketParser.get_arg(JSONKeys.data, packet.packetData) retain_flag = PacketParser.get_arg(JSONKeys.retainFlag, packet.packetData, False) qos = PacketParser.get_arg(JSONKeys.qos, packet.packetData, QOS.ZERO) if not self.is_channel_control(channel_name): status_code = await peer.callbackWrapper.validate_pub_callback(peer.client_id, channel_name, data, qos, peer.address, packet.protocol) if status_code != StatusCode.OK: log_msg = ('Pub FAILED channel {0} from client {1} , qos {3}, retain {4} {2} : status {5}').format(channel_name, peer.client_id, peer.id, qos, retain_flag, status_code) logger.log_warning(log_msg, peer.tag) else: log_msg = ('Pub OK channel {0} from client {1} , qos {3}, retain {4} {2}').format(channel_name, peer.client_id, peer.id, qos, retain_flag) logger.log_debug(log_msg, peer.tag) if status_code == StatusCode.OK: status_code = await self.pub(peer.client_id, channel_name, data, retain_flag, qos) # check qos, only send pub ack if qos is 1 if qos == QOS.ONE: response = PacketGenerator.generate_pub_res(status_code, pck_id) else: status_code, response_data = await peer.callbackWrapper.control_data_callback(peer.client_id, channel_name, data, peer.address, packet.protocol) response = PacketGenerator.generate_pub_res(status_code, pck_id, response_data) log_msg = ('Control Pub channel {0} from client {1} {2} : status {3}').format(channel_name, peer.client_id, peer.id, status_code) logger.log_info(log_msg, peer.tag) else: status_code = StatusCode.INVALID_CHANNEL response = PacketGenerator.generate_pub_res(status_code, pck_id) msg = ('Pub INVALID channel {0} from client {1} {2}').format(channel_name, peer.client_id, peer.id) logger.log_warning(msg, peer.tag) #pushAck handler elif packet.packetType == PacketTypes.pushAck: pck_id = PacketParser.get_arg(JSONKeys.packetId, packet.packetData) await self.process_push_ack(pck_id, peer.client_id) log_msg = ('PushAck for pck id {2} from client {0} {1}').format(peer.client_id, peer.id, pck_id) logger.log_debug(log_msg, peer.tag) #sub handler elif packet.packetType == PacketTypes.sub: channel_name = PacketParser.get_arg(JSONKeys.channelName, packet.packetData) persistent_flag = PacketParser.get_arg(JSONKeys.persistent, packet.packetData, False) channel_valid, channel_name = self.is_channel_valid(channel_name) if channel_valid: status_code = await peer.callbackWrapper.validate_sub_callback(peer.client_id, channel_name, persistent_flag, peer.address, packet.protocol) else: status_code = StatusCode.INVALID_CHANNEL if status_code == StatusCode.OK: status_code = await self.sub(peer.client_id, channel_name, persistent_flag) response = PacketGenerator.generate_sub_res(status_code, channel_name) if status_code != StatusCode.OK: log_msg = ('Sub FAILED channel {0} with persistent {4} from client {1} {2} : status {3}').format(channel_name, peer.client_id, peer.id, status_code, persistent_flag) logger.log_warning(log_msg, peer.tag) else: log_msg = ('Sub OK channel {0} with persistent {3} from client {1} {2}').format(channel_name, peer.client_id, peer.id, persistent_flag) logger.log_debug(log_msg, peer.tag) #unsub handler elif packet.packetType == PacketTypes.unsub: channel_name = PacketParser.get_arg(JSONKeys.channelName, packet.packetData) channel_valid, channel_name = self.is_channel_valid(channel_name) if channel_valid: status_code = await peer.callbackWrapper.validate_unsub_callback(peer.client_id, channel_name, peer.address, packet.protocol) else: status_code = StatusCode.INVALID_CHANNEL if status_code == StatusCode.OK: status_code = await self.unsub(peer.client_id, channel_name) response = PacketGenerator.generate_unsub_res(status_code, channel_name) if status_code != StatusCode.OK: log_msg = ('Unsub FAILED channel {0} from client {1} {2} : status {3}').format(channel_name, peer.client_id, peer.id, status_code) logger.log_warning(log_msg, peer.tag) else: log_msg = ('Unsub OK channel {0} from client {1} {2}').format(channel_name, peer.client_id, peer.id) logger.log_debug(log_msg, peer.tag) #hb handler elif packet.packetType == PacketTypes.hb: await self.heartbeat(peer.client_id) log_msg = ('Heartbeat from client {0} {1}').format(peer.client_id, peer.id) logger.log_debug(log_msg, peer.tag) if peer.client_id != None: response = PacketGenerator.generate_heartbeat_res() else: logger.log_info('WARNING: access without connecting from peer ' + str(peer.id), 'create_response') response = None return (response, data)