D901 #2

Merged
bmartin5692 merged 34 commits from D901 into dev 2019-02-22 05:37:44 +01:00
5 changed files with 268 additions and 269 deletions
Showing only changes of commit e17a0cb30b - Show all commits

View file

@ -72,11 +72,11 @@ def main():
# if uid != "": # if uid != "":
# xmpp_server.remove_client_byuid(uid) #Remove clients from xmpp server # xmpp_server.remove_client_byuid(uid) #Remove clients from xmpp server
# remove_clients.remove(uid) # remove_clients.remove(uid)
# bumper.bumper_removeclients_var.set(remove_clients) # bumper.bumper_removeclients_var.set(remove_clients)
except KeyboardInterrupt: except KeyboardInterrupt:
bumper.bumperlog.info("Bumper Exiting - Keyboard Interrupt") bumper.bumperlog.info("Bumper Exiting - Keyboard Interrupt")
print("Bumper Exiting") print("Bumper Exiting")
exit(1) exit(1)

View file

@ -70,7 +70,7 @@ class BumperUser(object):
def revoke_authcode(self, authcode): def revoke_authcode(self, authcode):
if authcode in self.authcodes: if authcode in self.authcodes:
self.authcodes.remove(authcode) self.authcodes.remove(authcode)
def add_bot(self, botdid): def add_bot(self, botdid):
if not botdid in self.bots: if not botdid in self.bots:
@ -78,7 +78,7 @@ class BumperUser(object):
def remove_bot(self, botdid): def remove_bot(self, botdid):
if botdid in self.bots: if botdid in self.bots:
self.bots.remove(botdid) self.bots.remove(botdid)
class VacBotDevice(object): class VacBotDevice(object):
def __init__(self,did="", vac_bot_device_class="",resource="" , name="", nick="", company="eco-ng"): def __init__(self,did="", vac_bot_device_class="",resource="" , name="", nick="", company="eco-ng"):
@ -128,7 +128,7 @@ def add_bot(sn, did, devclass, resource):
if bot.did == newbot.did: if bot.did == newbot.did:
existingbot = True existingbot = True
if existingbot == False: if existingbot == False:
bots.append(newbot) bots.append(newbot)
bumperlog.info("new bot added SN: {} DID: {}".format(newbot.name, newbot.did)) bumperlog.info("new bot added SN: {} DID: {}".format(newbot.name, newbot.did))
bumper_bots_var.set(bots) bumper_bots_var.set(bots)
@ -141,7 +141,7 @@ def add_client(userid, realm, resource):
newclient.resource = resource newclient.resource = resource
clients = bumper_clients_var.get() clients = bumper_clients_var.get()
existingclient = False existingclient = False
for client in clients: for client in clients:
if client.userid == newclient.userid: if client.userid == newclient.userid:

View file

@ -17,7 +17,7 @@ class aiohttp_filter(logging.Filter):
def filter(self, record): def filter(self, record):
if record.name == "aiohttp.access" and record.levelno == 20: #Filters aiohttp.access log to switch it from INFO to DEBUG if record.name == "aiohttp.access" and record.levelno == 20: #Filters aiohttp.access log to switch it from INFO to DEBUG
record.levelno = 10 record.levelno = 10
record.levelname = "DEBUG" record.levelname = "DEBUG"
if record.levelno == 10 and logging.getLogger("confserver").getEffectiveLevel() == 10: if record.levelno == 10 and logging.getLogger("confserver").getEffectiveLevel() == 10:
return True return True
@ -44,13 +44,13 @@ class ConfServer():
def run(self, run_async=False): def run(self, run_async=False):
try: try:
if run_async: if run_async:
confserverlog.debug("Starting ConfServer Thread: 1") confserverlog.debug("Starting ConfServer Thread: 1")
self.confthread = Thread(name="ConfServer_{}_Thread".format(self.address[1]),target=self.run_server) self.confthread = Thread(name="ConfServer_{}_Thread".format(self.address[1]),target=self.run_server)
self.confthread.setDaemon(True) self.confthread.setDaemon(True)
self.confthread.start() self.confthread.start()
else: else:
try: try:
self.run_server() self.run_server()
@ -73,19 +73,19 @@ class ConfServer():
loop.run_until_complete(self.start_server()) loop.run_until_complete(self.start_server())
loop.run_forever() loop.run_forever()
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
async def start_server(self): async def start_server(self):
try: try:
app = web.Application() app = web.Application()
app.add_routes([ app.add_routes([
web.get('', self.handle_base), web.get('', self.handle_base),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login', self.handle_login), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login', self.handle_login),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin', self.handle_login), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin', self.handle_login),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/logout', self.handle_logout), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/logout', self.handle_logout),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getAuthCode', self.handle_getAuthCode), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getAuthCode', self.handle_getAuthCode),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreement', self.handle_checkAgreement), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreement', self.handle_checkAgreement),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/checkVersion', self.handle_checkVersion), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/checkVersion', self.handle_checkVersion),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/campaign/homePageAlert', self.handle_homePageAlert), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/campaign/homePageAlert', self.handle_homePageAlert),
@ -94,22 +94,20 @@ class ConfServer():
web.get('/api/users/user.do', self.handle_usersapi), web.get('/api/users/user.do', self.handle_usersapi),
web.post('/api/pim/product/getProductIotMap', self.handle_getProductIotMap), web.post('/api/pim/product/getProductIotMap', self.handle_getProductIotMap),
web.post('/api/iot/devmanager.do', self.handle_devmanager_botcommand), web.post('/api/iot/devmanager.do', self.handle_devmanager_botcommand),
web.post('/lookup.do', self.handle_lookup), web.post('/lookup.do', self.handle_lookup),
]) ])
#Direct register from app: #Direct register from app:
#/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/directRegister #/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/directRegister
runner = web.AppRunner(app) runner = web.AppRunner(app)
await runner.setup() await runner.setup()
if self.usessl: if self.usessl:
ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_ctx.load_cert_chain(bumper.server_cert,bumper.server_key) ssl_ctx.load_cert_chain(bumper.server_cert,bumper.server_key)
site = web.TCPSite(runner, host=self.address[0], port=self.address[1],ssl_context=ssl_ctx) site = web.TCPSite(runner, host=self.address[0], port=self.address[1],ssl_context=ssl_ctx)
else: else:
site = web.TCPSite(runner, host=self.address[0], port=self.address[1]) site = web.TCPSite(runner, host=self.address[0], port=self.address[1])
@ -121,18 +119,18 @@ class ConfServer():
exit(1) exit(1)
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
exit(1) exit(1)
async def handle_base(self, request): async def handle_base(self, request):
try: try:
text = "Bumper!" text = "Bumper!"
return web.json_response(text) return web.json_response(text)
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
async def handle_login(self, request): async def handle_login(self, request):
try: try:
@ -141,10 +139,10 @@ class ConfServer():
confserverlog.info('client with devid {} attempting login'.format(user_devid)) confserverlog.info('client with devid {} attempting login'.format(user_devid))
if bumper.use_auth: if bumper.use_auth:
if not user_devid == "": #Performing basic "auth" using devid, super insecure if not user_devid == "": #Performing basic "auth" using devid, super insecure
users = self.bumper_users.get() users = self.bumper_users.get()
for user in users: for user in users:
if user_devid in user.devices: if user_devid in user.devices:
tmpaccesstoken = '' tmpaccesstoken = ''
if 'checkLogin' in request.path: if 'checkLogin' in request.path:
if request.query['accessToken'] in user.tokens and request.query['uid'] == "fuid_{}".format(user.userid): if request.query['accessToken'] in user.tokens and request.query['uid'] == "fuid_{}".format(user.userid):
tmpaccesstoken = request.query['accessToken'] tmpaccesstoken = request.query['accessToken']
@ -166,12 +164,12 @@ class ConfServer():
"data": None, "data": None,
"msg": "当前密码错误", "msg": "当前密码错误",
"time": bumper.get_milli_time(time.time()) "time": bumper.get_milli_time(time.time())
} }
else: else:
if tmpaccesstoken == '': if tmpaccesstoken == '':
tmpaccesstoken = uuid.uuid4().hex tmpaccesstoken = uuid.uuid4().hex
user.add_token(tmpaccesstoken) user.add_token(tmpaccesstoken)
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": { "data": {
@ -184,38 +182,38 @@ class ConfServer():
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(time.time()) "time": bumper.get_milli_time(time.time())
} }
self.bumper_users.set(users) self.bumper_users.set(users)
return web.json_response(body) return web.json_response(body)
body = { body = {
"code": bumper.ERR_USER_NOT_ACTIVATED, "code": bumper.ERR_USER_NOT_ACTIVATED,
"data": None, "data": None,
"msg": "当前密码错误", "msg": "当前密码错误",
"time": bumper.get_milli_time(time.time()) "time": bumper.get_milli_time(time.time())
} }
return web.json_response(body) return web.json_response(body)
else: else:
return web.json_response(self._auth_any(user_devid, countrycode, request)) return web.json_response(self._auth_any(user_devid, countrycode, request))
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
def _auth_any(self, devid, country, request): def _auth_any(self, devid, country, request):
try: try:
user_devid = devid user_devid = devid
countrycode = country countrycode = country
tmpaccesstoken = '' tmpaccesstoken = ''
users = self.bumper_users.get() users = self.bumper_users.get()
bots = self.bumper_bots.get() bots = self.bumper_bots.get()
if len(users) > 0: if len(users) > 0:
tmpuser = users[0] tmpuser = users[0]
tmpuser.add_device(user_devid) tmpuser.add_device(user_devid)
else: else:
tmpuser = bumper.BumperUser('tmpuser') tmpuser = bumper.BumperUser('tmpuser')
users.append(tmpuser) users.append(tmpuser)
tmpuser.add_device(user_devid) tmpuser.add_device(user_devid)
@ -223,7 +221,7 @@ class ConfServer():
for bot in bots: for bot in bots:
tmpuser.add_bot(bot.did) tmpuser.add_bot(bot.did)
if 'checkLogin' in request.path: if 'checkLogin' in request.path:
tmpaccesstoken = request.query['accessToken'] tmpaccesstoken = request.query['accessToken']
tmpuser.add_token(tmpaccesstoken) tmpuser.add_token(tmpaccesstoken)
body = { body = {
@ -242,7 +240,7 @@ class ConfServer():
if tmpaccesstoken == '': if tmpaccesstoken == '':
tmpaccesstoken = uuid.uuid4().hex tmpaccesstoken = uuid.uuid4().hex
tmpuser.add_token(tmpaccesstoken) tmpuser.add_token(tmpaccesstoken)
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": { "data": {
@ -255,44 +253,44 @@ class ConfServer():
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(time.time()) "time": bumper.get_milli_time(time.time())
} }
self.bumper_users.set(users) self.bumper_users.set(users)
return body return body
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
async def handle_logout(self, request): async def handle_logout(self, request):
try: try:
user_devid = request.match_info.get('devid', "") user_devid = request.match_info.get('devid', "")
if not user_devid == "": if not user_devid == "":
users = self.bumper_users.get() users = self.bumper_users.get()
for user in users: for user in users:
if user_devid in user.devices: if user_devid in user.devices:
if request.query['uid'] == "fuid_{}".format(user.userid) and request.query['accessToken'] in user.tokens: if request.query['uid'] == "fuid_{}".format(user.userid) and request.query['accessToken'] in user.tokens:
user.revoke_token(request.query['accessToken']) user.revoke_token(request.query['accessToken'])
self.bumper_users.set(users) self.bumper_users.set(users)
body = {"code": bumper.RETURN_API_SUCCESS,"data": None,"msg": "操作成功", "time": bumper.get_milli_time(time.time())} body = {"code": bumper.RETURN_API_SUCCESS,"data": None,"msg": "操作成功", "time": bumper.get_milli_time(time.time())}
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
async def handle_getAuthCode(self, request): async def handle_getAuthCode(self, request):
try: try:
user_devid = request.match_info.get('devid', "") user_devid = request.match_info.get('devid', "")
if not user_devid == "": if not user_devid == "":
users = self.bumper_users.get() users = self.bumper_users.get()
if len(users) > 0: if len(users) > 0:
for user in users: for user in users:
if user_devid in user.devices and request.query['accessToken'] in user.tokens: if user_devid in user.devices and request.query['accessToken'] in user.tokens:
countrycode = request.match_info.get('country', "us") countrycode = request.match_info.get('country', "us")
tmpauthcode = "{}_{}".format(countrycode,uuid.uuid4().hex) tmpauthcode = "{}_{}".format(countrycode,uuid.uuid4().hex)
user.add_authcode(tmpauthcode) user.add_authcode(tmpauthcode)
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": { "data": {
@ -310,14 +308,14 @@ class ConfServer():
"data": None, "data": None,
"msg": "当前密码错误", "msg": "当前密码错误",
"time": bumper.get_milli_time(time.time()) "time": bumper.get_milli_time(time.time())
} }
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
async def handle_checkVersion(self, request): async def handle_checkVersion(self, request):
try: try:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
@ -333,31 +331,31 @@ class ConfServer():
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(time.time()) "time": bumper.get_milli_time(time.time())
} }
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
async def handle_checkAgreement(self, request): async def handle_checkAgreement(self, request):
try: try:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": [], "data": [],
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(time.time()) "time": bumper.get_milli_time(time.time())
} }
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
async def handle_homePageAlert(self, request): async def handle_homePageAlert(self, request):
try: try:
nextAlert = bumper.get_milli_time((datetime.now() + timedelta(hours=12)).timestamp()) nextAlert = bumper.get_milli_time((datetime.now() + timedelta(hours=12)).timestamp())
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": { "data": {
@ -371,19 +369,19 @@ class ConfServer():
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(time.time()) "time": bumper.get_milli_time(time.time())
} }
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
async def handle_getProductIotMap(self, request): async def handle_getProductIotMap(self, request):
try: try:
body = {"code":bumper.RETURN_API_SUCCESS,"data":[{"classid":"dl8fht","product":{"_id":"5acb0fa87c295c0001876ecf","name":"DEEBOT 600 Series","icon":"5acc32067c295c0001876eea","UILogicId":"dl8fht","ota":False,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5acc32067c295c0001876eea"}},{"classid":"02uwxm","product":{"_id":"5ae1481e7ccd1a0001e1f69e","name":"DEEBOT OZMO Slim10 Series","icon":"5b1dddc48bc45700014035a1","UILogicId":"02uwxm","ota":False,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b1dddc48bc45700014035a1"}},{"classid":"y79a7u","product":{"_id":"5b04c0227ccd1a0001e1f6a8","name":"DEEBOT OZMO 900","icon":"5b04c0217ccd1a0001e1f6a7","UILogicId":"y79a7u","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b04c0217ccd1a0001e1f6a7"}},{"classid":"jr3pqa","product":{"_id":"5b43077b8bc457000140363e","name":"DEEBOT 711","icon":"5b5ac4cc8d5a56000111e769","UILogicId":"jr3pqa","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4cc8d5a56000111e769"}},{"classid":"uv242z","product":{"_id":"5b5149b4ac0b87000148c128","name":"DEEBOT 710","icon":"5b5ac4e45f21100001882bb9","UILogicId":"uv242z","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4e45f21100001882bb9"}},{"classid":"ls1ok3","product":{"_id":"5b6561060506b100015c8868","name":"DEEBOT 900 Series","icon":"5ba4a2cb6c2f120001c32839","UILogicId":"ls1ok3","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5ba4a2cb6c2f120001c32839"}}]} body = {"code":bumper.RETURN_API_SUCCESS,"data":[{"classid":"dl8fht","product":{"_id":"5acb0fa87c295c0001876ecf","name":"DEEBOT 600 Series","icon":"5acc32067c295c0001876eea","UILogicId":"dl8fht","ota":False,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5acc32067c295c0001876eea"}},{"classid":"02uwxm","product":{"_id":"5ae1481e7ccd1a0001e1f69e","name":"DEEBOT OZMO Slim10 Series","icon":"5b1dddc48bc45700014035a1","UILogicId":"02uwxm","ota":False,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b1dddc48bc45700014035a1"}},{"classid":"y79a7u","product":{"_id":"5b04c0227ccd1a0001e1f6a8","name":"DEEBOT OZMO 900","icon":"5b04c0217ccd1a0001e1f6a7","UILogicId":"y79a7u","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b04c0217ccd1a0001e1f6a7"}},{"classid":"jr3pqa","product":{"_id":"5b43077b8bc457000140363e","name":"DEEBOT 711","icon":"5b5ac4cc8d5a56000111e769","UILogicId":"jr3pqa","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4cc8d5a56000111e769"}},{"classid":"uv242z","product":{"_id":"5b5149b4ac0b87000148c128","name":"DEEBOT 710","icon":"5b5ac4e45f21100001882bb9","UILogicId":"uv242z","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4e45f21100001882bb9"}},{"classid":"ls1ok3","product":{"_id":"5b6561060506b100015c8868","name":"DEEBOT 900 Series","icon":"5ba4a2cb6c2f120001c32839","UILogicId":"ls1ok3","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5ba4a2cb6c2f120001c32839"}}]}
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
async def handle_usersapi(self, request): async def handle_usersapi(self, request):
try: try:
@ -392,10 +390,10 @@ class ConfServer():
postbody = {} postbody = {}
if request.content_type == "application/x-www-form-urlencoded": if request.content_type == "application/x-www-form-urlencoded":
postbody = await request.post() postbody = await request.post()
else: else:
postbody = json.loads(await request.text()) postbody = json.loads(await request.text())
todo = postbody['todo'] todo = postbody['todo']
if todo == 'FindBest': if todo == 'FindBest':
service = postbody['service'] service = postbody['service']
@ -404,10 +402,10 @@ class ConfServer():
elif service == 'EcoUpdate': elif service == 'EcoUpdate':
body = {"result":"ok","ip":"47.88.66.164","port":8005} body = {"result":"ok","ip":"47.88.66.164","port":8005}
elif todo == 'loginByItToken': elif todo == 'loginByItToken':
users = self.bumper_users.get() users = self.bumper_users.get()
for user in users: for user in users:
if postbody['userId'] == "fuid_{}".format(user.userid) and postbody['token'] in user.authcodes: if postbody['userId'] == "fuid_{}".format(user.userid) and postbody['token'] in user.authcodes:
body = { body = {
"resource": postbody["resource"], "resource": postbody["resource"],
"result": "ok", "result": "ok",
@ -425,20 +423,20 @@ class ConfServer():
"devices": bot_list, "devices": bot_list,
"result": "ok", "result": "ok",
"todo": "result" "todo": "result"
} }
elif todo == 'SetDeviceNick': elif todo == 'SetDeviceNick':
bots = self.bumper_bots.get() bots = self.bumper_bots.get()
for bot in bots: for bot in bots:
if postbody['did'] == bot.did: if postbody['did'] == bot.did:
bot.nick = postbody['nick'] bot.nick = postbody['nick']
self.bumper_bots.set(bots) self.bumper_bots.set(bots)
body = { body = {
"result": "ok", "result": "ok",
"todo": "result", "todo": "result",
} }
confserverlog.debug("\r\n POST: {} \r\n Response: {}".format(postbody,body)) confserverlog.debug("\r\n POST: {} \r\n Response: {}".format(postbody,body))
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
@ -451,12 +449,12 @@ class ConfServer():
postbody = {} postbody = {}
if request.content_type == "application/x-www-form-urlencoded": if request.content_type == "application/x-www-form-urlencoded":
postbody = await request.post() postbody = await request.post()
else: else:
postbody = json.loads(await request.text()) postbody = json.loads(await request.text())
confserverlog.debug(postbody) confserverlog.debug(postbody)
todo = postbody['todo'] todo = postbody['todo']
if todo == 'FindBest': if todo == 'FindBest':
service = postbody['service'] service = postbody['service']
@ -464,23 +462,23 @@ class ConfServer():
body = {"result":"ok","ip":socket.gethostbyname(socket.gethostname()),"port":5223} body = {"result":"ok","ip":socket.gethostbyname(socket.gethostname()),"port":5223}
elif service == 'EcoUpdate': elif service == 'EcoUpdate':
body = {"result":"ok","ip":"47.88.66.164","port":8005} body = {"result":"ok","ip":"47.88.66.164","port":8005}
confserverlog.debug("\r\n POST: {} \r\n Response: {}".format(postbody,body)) confserverlog.debug("\r\n POST: {} \r\n Response: {}".format(postbody,body))
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:
confserverlog.exception('{}'.format(e)) confserverlog.exception('{}'.format(e))
async def handle_devmanager_botcommand(self, request): async def handle_devmanager_botcommand(self, request):
try: try:
json_body = json.loads(await request.text()) json_body = json.loads(await request.text())
randomid = ''.join(random.sample(string.ascii_letters,6)) randomid = ''.join(random.sample(string.ascii_letters,6))
bots = self.bumper_bots.get() bots = self.bumper_bots.get()
for bot in bots: for bot in bots:
if bot.did == json_body['toId'] and bot.mqtt_connection == True: if bot.did == json_body['toId'] and bot.mqtt_connection == True:
retcmd = await self.helperbot.send_command(json_body, randomid) retcmd = await self.helperbot.send_command(json_body, randomid)
body = retcmd body = retcmd
confserverlog.debug("\r\n POST: {} \r\n Response: {}".format(json_body,body)) confserverlog.debug("\r\n POST: {} \r\n Response: {}".format(json_body,body))
return web.json_response(body) return web.json_response(body)
else: else:
confserverlog.error("No bots with DID: {} connected to MQTT".format(json_body['toId'])) confserverlog.error("No bots with DID: {} connected to MQTT".format(json_body['toId']))

View file

@ -37,12 +37,12 @@ class MQTTHelperBot():
def run(self, run_async=False): def run(self, run_async=False):
if run_async: if run_async:
hloop = asyncio.new_event_loop() hloop = asyncio.new_event_loop()
helperbotlog.debug("Starting MQTT HelperBot Thread: 1") helperbotlog.debug("Starting MQTT HelperBot Thread: 1")
self.helperthread = Thread(name="MQTTHelperBot_Thread",target=self.run_helperbot, args=(hloop,)) self.helperthread = Thread(name="MQTTHelperBot_Thread",target=self.run_helperbot, args=(hloop,))
self.helperthread.setDaemon(True) self.helperthread.setDaemon(True)
self.helperthread.start() self.helperthread.start()
else: else:
self.run_helperbot() self.run_helperbot()
@ -51,13 +51,13 @@ class MQTTHelperBot():
logging.info("Starting MQTT HelperBot") logging.info("Starting MQTT HelperBot")
print("Starting MQTT HelperBot") print("Starting MQTT HelperBot")
try: try:
asyncio.set_event_loop(loop) asyncio.set_event_loop(loop)
self.Client = MQTTClient(client_id=self.client_id, config={'check_hostname':False}) self.Client = MQTTClient(client_id=self.client_id, config={'check_hostname':False})
loop.run_until_complete(self.start_helper_bot()) loop.run_until_complete(self.start_helper_bot())
loop.run_until_complete(self.get_msg()) loop.run_until_complete(self.get_msg())
loop.run_forever() loop.run_forever()
except Exception as e: except Exception as e:
helperbotlog.exception('{}'.format(e)) helperbotlog.exception('{}'.format(e))
async def start_helper_bot(self): async def start_helper_bot(self):
@ -65,41 +65,41 @@ class MQTTHelperBot():
await self.Client.connect('mqtts://{}:{}/'.format(self.address[0], self.address[1]), cafile=bumper.ca_cert) await self.Client.connect('mqtts://{}:{}/'.format(self.address[0], self.address[1]), cafile=bumper.ca_cert)
await self.Client.subscribe([ await self.Client.subscribe([
('iot/p2p/+/+/+/+/helper1/bumper/helper1/+/+/+',QOS_0), ('iot/p2p/+/+/+/+/helper1/bumper/helper1/+/+/+',QOS_0),
('iot/p2p/+',QOS_0) ('iot/p2p/+',QOS_0)
]) ])
except Exception as e: except Exception as e:
helperbotlog.exception('{}'.format(e)) helperbotlog.exception('{}'.format(e))
async def get_msg(self): async def get_msg(self):
try: try:
while True: while True:
message = await self.Client.deliver_message() message = await self.Client.deliver_message()
#helperbotlog.debug("HelperBot MQTT Received Message on Topic: {} - Message: {}".format(message.topic, str(message.payload.decode("utf-8")))) #helperbotlog.debug("HelperBot MQTT Received Message on Topic: {} - Message: {}".format(message.topic, str(message.payload.decode("utf-8"))))
cresp = self.command_responses.get() cresp = self.command_responses.get()
if (str(message.topic).split("/")[6] == "helper1"): if (str(message.topic).split("/")[6] == "helper1"):
cresp.append({"time": time.time() ,"topic": message.topic,"payload":str(message.data.decode("utf-8"))}) cresp.append({"time": time.time() ,"topic": message.topic,"payload":str(message.data.decode("utf-8"))})
#Cleanup "expired messages" > 60 seconds from time #Cleanup "expired messages" > 60 seconds from time
for msg in cresp: for msg in cresp:
expire_time = (datetime.fromtimestamp(msg['time']) + timedelta(seconds=10)).timestamp() expire_time = (datetime.fromtimestamp(msg['time']) + timedelta(seconds=10)).timestamp()
if time.time() > expire_time: if time.time() > expire_time:
#helperbotlog.debug("Pruning Message Time: {}, MsgTime: {}, MsgTime+60: {}".format(time.time(), msg['time'], expire_time)) #helperbotlog.debug("Pruning Message Time: {}, MsgTime: {}, MsgTime+60: {}".format(time.time(), msg['time'], expire_time))
cresp.remove(msg) cresp.remove(msg)
self.command_responses.set(cresp) self.command_responses.set(cresp)
#helperbotlog.debug("MQTT Command Response List Count: %s" %len(cresp)) #helperbotlog.debug("MQTT Command Response List Count: %s" %len(cresp))
except Exception as e: except Exception as e:
helperbotlog.exception('{}'.format(e)) helperbotlog.exception('{}'.format(e))
async def wait_for_resp(self, requestid): async def wait_for_resp(self, requestid):
try: try:
t_end = (datetime.now() + timedelta(seconds=10)).timestamp() t_end = (datetime.now() + timedelta(seconds=10)).timestamp()
while time.time() < t_end: while time.time() < t_end:
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
responses = self.command_responses.get() responses = self.command_responses.get()
@ -110,7 +110,7 @@ class MQTTHelperBot():
#helperbotlog.debug('VacBot MQTT Response: Topic: %s Payload: %s' % (msg['topic'], msg['payload'])) #helperbotlog.debug('VacBot MQTT Response: Topic: %s Payload: %s' % (msg['topic'], msg['payload']))
if topic[11] == "j": if topic[11] == "j":
resppayload = json.loads(msg['payload']) resppayload = json.loads(msg['payload'])
else: else:
resppayload = str(msg['payload']) resppayload = str(msg['payload'])
resp = { resp = {
"id": requestid, "id": requestid,
@ -118,28 +118,28 @@ class MQTTHelperBot():
"resp": resppayload "resp": resppayload
} }
cresp = self.command_responses.get() cresp = self.command_responses.get()
cresp.remove(msg) cresp.remove(msg)
self.command_responses.set(cresp) self.command_responses.set(cresp)
return resp return resp
return { "id": requestid, "errno": "timeout", "ret": "fail" } return { "id": requestid, "errno": "timeout", "ret": "fail" }
except asyncio.CancelledError as e: except asyncio.CancelledError as e:
helperbotlog.debug('wait_for_resp cancelled by asyncio') helperbotlog.debug('wait_for_resp cancelled by asyncio')
except Exception as e: except Exception as e:
helperbotlog.exception('{}'.format(e)) helperbotlog.exception('{}'.format(e))
async def send_command(self, cmdjson, requestid): async def send_command(self, cmdjson, requestid):
try: try:
ttopic = "iot/p2p/{}/helper1/bumper/helper1/{}/{}/{}/q/{}/{}".format(cmdjson["cmdName"], ttopic = "iot/p2p/{}/helper1/bumper/helper1/{}/{}/{}/q/{}/{}".format(cmdjson["cmdName"],
cmdjson["toId"], cmdjson["toType"], cmdjson["toRes"], requestid, cmdjson["payloadType"]) cmdjson["toId"], cmdjson["toType"], cmdjson["toRes"], requestid, cmdjson["payloadType"])
try: try:
await self.Client.publish(ttopic, str(cmdjson["payload"]).encode(),QOS_0) await self.Client.publish(ttopic, str(cmdjson["payload"]).encode(),QOS_0)
except Exception as e: except Exception as e:
helperbotlog.exception("{}".format(e)) helperbotlog.exception("{}".format(e))
resp = await self.wait_for_resp(requestid) resp = await self.wait_for_resp(requestid)
return resp return resp
except Exception as e: except Exception as e:
@ -156,7 +156,7 @@ class MQTTServer():
async def broker_coro(self): async def broker_coro(self):
try: try:
broker = hbmqtt.broker.Broker(config=self.default_config) broker = hbmqtt.broker.Broker(config=self.default_config)
await broker.start() await broker.start()
except PermissionError as e: except PermissionError as e:
if "bind" in e.strerror: if "bind" in e.strerror:
@ -174,7 +174,7 @@ class MQTTServer():
mqttserverlog.debug('connected bots - %s' % self.bumper_bots.get()) mqttserverlog.debug('connected bots - %s' % self.bumper_bots.get())
except Exception as e: except Exception as e:
mqttserverlog.exception('{}'.format(e)) mqttserverlog.exception('{}'.format(e))
def __init__(self, address,bumper_users=contextvars.ContextVar, bumper_bots=contextvars.ContextVar, bumper_clients=contextvars.ContextVar): def __init__(self, address,bumper_users=contextvars.ContextVar, bumper_bots=contextvars.ContextVar, bumper_clients=contextvars.ContextVar):
try: try:
@ -186,7 +186,7 @@ class MQTTServer():
#The below adds a plugin to the hbmqtt.broker.plugins without having to futz with setup.py #The below adds a plugin to the hbmqtt.broker.plugins without having to futz with setup.py
distribution = pkg_resources.Distribution("hbmqtt.broker.plugins") distribution = pkg_resources.Distribution("hbmqtt.broker.plugins")
bumper_plugin = pkg_resources.EntryPoint.parse('bumper = bumper.mqttserver:BumperMQTTServer_Plugin', dist=distribution) bumper_plugin = pkg_resources.EntryPoint.parse('bumper = bumper.mqttserver:BumperMQTTServer_Plugin', dist=distribution)
distribution._ep_map = {"hbmqtt.broker.plugins": {"bumper": bumper_plugin}} distribution._ep_map = {"hbmqtt.broker.plugins": {"bumper": bumper_plugin}}
pkg_resources.working_set.add(distribution) pkg_resources.working_set.add(distribution)
@ -218,22 +218,22 @@ class MQTTServer():
'bumper_users' : self.bumper_users, 'bumper_users' : self.bumper_users,
'bumper_bots': self.bumper_bots, 'bumper_bots': self.bumper_bots,
'bumper_clients': self.bumper_clients, 'bumper_clients': self.bumper_clients,
}, },
} }
except Exception as e: except Exception as e:
mqttserverlog.exception('{}'.format(e)) mqttserverlog.exception('{}'.format(e))
def run(self, run_async=False,): def run(self, run_async=False,):
if run_async: if run_async:
sloop = asyncio.new_event_loop() sloop = asyncio.new_event_loop()
mqttserverlog.debug("Starting MQTTServer Thread: 1") mqttserverlog.debug("Starting MQTTServer Thread: 1")
self.mqttserverthread = Thread(name="MQTTServer_Thread",target=self.run_server, args=(sloop,)) self.mqttserverthread = Thread(name="MQTTServer_Thread",target=self.run_server, args=(sloop,))
self.mqttserverthread.setDaemon(True) self.mqttserverthread.setDaemon(True)
self.mqttserverthread.start() self.mqttserverthread.start()
else: else:
self.run_server() self.run_server()
def run_server(self, loop): def run_server(self, loop):
@ -242,16 +242,16 @@ class MQTTServer():
try: try:
asyncio.set_event_loop(loop) asyncio.set_event_loop(loop)
loop.run_until_complete(self.broker_coro()) loop.run_until_complete(self.broker_coro())
#loop.run_until_complete(self.active_bot_listing()) #loop.run_until_complete(self.active_bot_listing())
loop.run_forever() loop.run_forever()
except Exception as e: except Exception as e:
mqttserverlog.exception('{}'.format(e)) mqttserverlog.exception('{}'.format(e))
class BumperMQTTServer_Plugin: class BumperMQTTServer_Plugin:
def __init__(self, context): def __init__(self, context):
self.context = context self.context = context
try: try:
self.bumper_config = self.context.config['bumper'] self.bumper_config = self.context.config['bumper']
self.auth_config = self.context.config['auth'] self.auth_config = self.context.config['auth']
@ -266,7 +266,7 @@ class BumperMQTTServer_Plugin:
# auth config section not found # auth config section not found
self.context.logger.warning("'auth' section not found in context configuration") self.context.logger.warning("'auth' section not found in context configuration")
return False return False
allow_anonymous = self.auth_config.get('allow-anonymous', True) # allow anonymous by default allow_anonymous = self.auth_config.get('allow-anonymous', True) # allow anonymous by default
if allow_anonymous: if allow_anonymous:
authenticated = True authenticated = True
@ -280,21 +280,21 @@ class BumperMQTTServer_Plugin:
username = session.username username = session.username
password = session.password password = session.password
client_id = session.client_id client_id = session.client_id
didsplit = str(client_id).split("@") didsplit = str(client_id).split("@")
#If this isn't a fake user (fuid) then add as a bot #If this isn't a fake user (fuid) then add as a bot
if not (str(didsplit[0]).startswith("fuid") or str(didsplit[0]).startswith("helper")): if not (str(didsplit[0]).startswith("fuid") or str(didsplit[0]).startswith("helper")):
tmpbotdetail = str(didsplit[1]).split("/") tmpbotdetail = str(didsplit[1]).split("/")
bumper.add_bot(username, didsplit[0], tmpbotdetail[0], tmpbotdetail[1]) bumper.add_bot(username, didsplit[0], tmpbotdetail[0], tmpbotdetail[1])
mqttserverlog.debug("new bot authenticated SN: {} DID: {}".format(username, didsplit[0])) mqttserverlog.debug("new bot authenticated SN: {} DID: {}".format(username, didsplit[0]))
authenticated = True authenticated = True
else: else:
tmpclientdetail = str(didsplit[1]).split("/") tmpclientdetail = str(didsplit[1]).split("/")
userid = didsplit[0] userid = didsplit[0]
realm = tmpclientdetail[0] realm = tmpclientdetail[0]
resource = tmpclientdetail[1] resource = tmpclientdetail[1]
if userid == "helper1": if userid == "helper1":
authenticated = True authenticated = True
else: else:
@ -306,17 +306,17 @@ class BumperMQTTServer_Plugin:
if auth: if auth:
bumper.add_client(userid, realm, resource) bumper.add_client(userid, realm, resource)
mqttserverlog.debug("client authenticated {}".format(userid)) mqttserverlog.debug("client authenticated {}".format(userid))
authenticated = True authenticated = True
else: else:
authenticated = False authenticated = False
except KeyError:
self.context.logger.warning("Session information not available")
authenticated = False
return authenticated
except Exception as e:
mqttserverlog.exception('{}'.format(e))
authenticated = False
return authenticated
async def on_broker_client_connected(self, client_id): async def on_broker_client_connected(self, client_id):
try: try:
@ -324,40 +324,40 @@ class BumperMQTTServer_Plugin:
bumper_bots = self.bumper_config['bumper_bots'].get() bumper_bots = self.bumper_config['bumper_bots'].get()
bumper_clients = self.bumper_config['bumper_clients'].get() bumper_clients = self.bumper_config['bumper_clients'].get()
didsplit = str(client_id).split("@") didsplit = str(client_id).split("@")
for bot in bumper_bots: for bot in bumper_bots:
if didsplit[0] == bot.did: if didsplit[0] == bot.did:
bot.mqtt_connection = True bot.mqtt_connection = True
#mqttserverlog.info("bot connected {}".format(bot.did)) mqttserverlog.debug("bot connected {}".format(bot.did))
self.bumper_config['bumper_bots'].set(bumper_bots) self.bumper_config['bumper_bots'].set(bumper_bots)
for client in bumper_clients: for client in bumper_clients:
if didsplit[0] == client.userid and client.userid != 'helper1': if didsplit[0] == client.userid and client.userid != 'helper1':
client.mqtt_connection = True client.mqtt_connection = True
#mqttserverlog.info("client connected {}".format(client.userid)) #mqttserverlog.info("client connected {}".format(client.userid))
self.bumper_config['bumper_clients'].set(bumper_clients) self.bumper_config['bumper_clients'].set(bumper_clients)
except Exception as e: except Exception as e:
mqttserverlog.exception('{}'.format(e)) mqttserverlog.exception('{}'.format(e))
async def on_broker_client_disconnected(self, client_id): async def on_broker_client_disconnected(self, client_id):
try: try:
bumper_users = self.bumper_config['bumper_users'].get() bumper_users = self.bumper_config['bumper_users'].get()
bumper_bots = self.bumper_config['bumper_bots'].get() bumper_bots = self.bumper_config['bumper_bots'].get()
bumper_clients = self.bumper_config['bumper_clients'].get() bumper_clients = self.bumper_config['bumper_clients'].get()
didsplit = str(client_id).split("@") didsplit = str(client_id).split("@")
for bot in bumper_bots: for bot in bumper_bots:
if didsplit[0] == bot.did: if didsplit[0] == bot.did:
bot.mqtt_connection = False bot.mqtt_connection = False
#mqttserverlog.info("bot disconnected {}".format(bot.did)) mqttserverlog.debug("bot disconnected {}".format(bot.did))
self.bumper_config['bumper_bots'].set(bumper_bots) self.bumper_config['bumper_bots'].set(bumper_bots)
for client in bumper_clients: for client in bumper_clients:
if didsplit[0] == client.userid and client.userid != 'helper1': if didsplit[0] == client.userid and client.userid != 'helper1':
client.mqtt_connection = False client.mqtt_connection = False
#mqttserverlog.info("client disconnected {}".format(client.userid)) #mqttserverlog.info("client disconnected {}".format(client.userid))
self.bumper_config['bumper_clients'].set(bumper_clients) self.bumper_config['bumper_clients'].set(bumper_clients)
except Exception as e: except Exception as e:

View file

@ -27,10 +27,10 @@ class XMPPServer():
def run(self, run_async=False): def run(self, run_async=False):
if run_async: if run_async:
xmppserverlog.debug("Starting XMPPServer Thread: 1") xmppserverlog.debug("Starting XMPPServer Thread: 1")
self.xmppthread = Thread(name="XMPPServer_Thread",target=self.run_server) self.xmppthread = Thread(name="XMPPServer_Thread",target=self.run_server)
self.xmppthread.setDaemon(True) self.xmppthread.setDaemon(True)
self.xmppthread.start() self.xmppthread.start()
else: else:
try: try:
self.run_server() self.run_server()
@ -44,39 +44,39 @@ class XMPPServer():
#xmppserverlog.setLevel(logging.DEBUG) #xmppserverlog.setLevel(logging.DEBUG)
#Set SSL Context #Set SSL Context
self.ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) self.ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
self.ssl_ctx.load_cert_chain(certfile=bumper.server_cert,keyfile=bumper.server_key) self.ssl_ctx.load_cert_chain(certfile=bumper.server_cert,keyfile=bumper.server_key)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try: try:
self.socket.bind(self.address) self.socket.bind(self.address)
self.socket.listen(5) self.socket.listen(5)
xmppserverlog.debug('listening on {}:{}'.format(self.address[0], self.address[1])) xmppserverlog.debug('listening on {}:{}'.format(self.address[0], self.address[1]))
while not self.exit_flag: while not self.exit_flag:
connection, client_address = self.socket.accept() connection, client_address = self.socket.accept()
# disconnect any clients with this ip # disconnect any clients with this ip
for client in self.clients: for client in self.clients:
if client.address == client_address[0]: if client.address == client_address[0]:
xmppserverlog.debug('disconnecting existing client {} with resource {}'.format(client.address, client.clientresource)) xmppserverlog.debug('disconnecting existing client {} with resource {}'.format(client.address, client.clientresource))
client._disconnect() client._disconnect()
self.remove_client_byip(client.address) self.remove_client_byip(client.address)
xmppserverlog.debug('starting new client with ip {}'.format(client_address[0])) xmppserverlog.debug('starting new client with ip {}'.format(client_address[0]))
thread_id = uuid.uuid4() thread_id = uuid.uuid4()
client = Client(thread_id, connection, client_address, self.bumper_users, self.bumper_bots, self.bumper_clients) client = Client(thread_id, connection, client_address, self.bumper_users, self.bumper_bots, self.bumper_clients)
client.setDaemon(True) client.setDaemon(True)
client.start() client.start()
self.clients.append(client) self.clients.append(client)
except PermissionError as e: except PermissionError as e:
if "bind" in e.strerror: if "bind" in e.strerror:
xmppserverlog.exception("Error binding XMPPServer, exiting. Try using a different hostname or IP - {}".format(e)) xmppserverlog.exception("Error binding XMPPServer, exiting. Try using a different hostname or IP - {}".format(e))
exit(1) exit(1)
except Exception as e: except Exception as e:
xmppserverlog.exception('{}'.format(e)) xmppserverlog.exception('{}'.format(e))
exit(1) exit(1)
@ -88,16 +88,16 @@ class XMPPServer():
connection.shutdown(socket.SHUT_RDWR) connection.shutdown(socket.SHUT_RDWR)
connection.close() connection.close()
self.disconnect() self.disconnect()
xmppserverlog.info('disconnecting') xmppserverlog.info('disconnecting')
self.socket.close() self.socket.close()
def disconnect(self): def disconnect(self):
try: try:
xmppserverlog.debug('waiting for all client threads to exit') xmppserverlog.debug('waiting for all client threads to exit')
for client in self.clients: for client in self.clients:
client._disconnect() client._disconnect()
self.exit_flag = True self.exit_flag = True
xmppserverlog.debug('shutting down') xmppserverlog.debug('shutting down')
@ -172,11 +172,11 @@ class Client(threading.Thread):
except ConnectionResetError as e: except ConnectionResetError as e:
xmppserverlog.error('{}'.format(e)) xmppserverlog.error('{}'.format(e))
#self._set_state('DISCONNECT') #self._set_state('DISCONNECT')
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))
def _disconnect(self): def _disconnect(self):
try: try:
@ -186,14 +186,14 @@ class Client(threading.Thread):
if self.uid == bot.did: if self.uid == bot.did:
bot.xmpp_connection = False bot.xmpp_connection = False
#xmppserverlog.info("bot disconnected {}".format(bot.did)) #xmppserverlog.info("bot disconnected {}".format(bot.did))
self.bumper_bots.set(bumper_bots) self.bumper_bots.set(bumper_bots)
for client in bumper_clients: for client in bumper_clients:
if self.uid == client.userid and client.userid != 'helper1': if self.uid == client.userid and client.userid != 'helper1':
client.xmpp_connection = False client.xmpp_connection = False
#xmppserverlog.info("client disconnected {}".format(client.userid)) #xmppserverlog.info("client disconnected {}".format(client.userid))
self.bumper_clients.set(bumper_clients) self.bumper_clients.set(bumper_clients)
#xmppserverlog.debug('client {} with resource {} disconnecting'.format(self.address, self.clientresource)) #xmppserverlog.debug('client {} with resource {} disconnecting'.format(self.address, self.clientresource))
self.connection.close() self.connection.close()
@ -215,29 +215,29 @@ class Client(threading.Thread):
new_state = getattr(Client, state) new_state = getattr(Client, state)
if self.state > new_state: if self.state > new_state:
raise Exception('{} illegal state change {}->{}'.format(self.address, self.state, new_state)) raise Exception('{} illegal state change {}->{}'.format(self.address, self.state, new_state))
xmppserverlog.debug('{} state: {}'.format(self.address, state)) xmppserverlog.debug('{} state: {}'.format(self.address, state))
self.state = new_state self.state = new_state
if new_state == 5: if new_state == 5:
self._disconnect() self._disconnect()
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))
def _handle_ctl(self, xml, data): def _handle_ctl(self, xml, data):
try: try:
if data.decode('utf-8').find('roster') > -1: if data.decode('utf-8').find('roster') > -1:
#Return not-implemented for roster #Return not-implemented for roster
self.send('<iq type="error" id="{}"><error type="cancel" code="501"><feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>'.format(xml.get('id'))) self.send('<iq type="error" id="{}"><error type="cancel" code="501"><feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>'.format(xml.get('id')))
return return
if xml.get('type') == 'set': if xml.get('type') == 'set':
if data.decode('utf-8').find('com:sf') > -1 and xml.get('to') == 'rl.ecorobot.net': #Android bind? Not sure what this does yet. if data.decode('utf-8').find('com:sf') > -1 and xml.get('to') == 'rl.ecorobot.net': #Android bind? Not sure what this does yet.
self.send('<iq id="{}" to="{}@{}/{}" from="rl.ecorobot.net" type="result"/>'.format(xml.get('id'), self.uid, XMPPServer.bot_id, self.clientresource)) self.send('<iq id="{}" to="{}@{}/{}" from="rl.ecorobot.net" type="result"/>'.format(xml.get('id'), self.uid, XMPPServer.bot_id, self.clientresource))
else: else:
xmppserverlog.debug('Unknown set type: {}'.format(data.decode('utf-8'))) xmppserverlog.debug('Unknown set type: {}'.format(data.decode('utf-8')))
@ -246,7 +246,7 @@ class Client(threading.Thread):
if ctl.get('admin') and self.type == self.BOT: if ctl.get('admin') and self.type == self.BOT:
xmppserverlog.debug('admin username received from bot: {}'.format(ctl.get('admin'))) xmppserverlog.debug('admin username received from bot: {}'.format(ctl.get('admin')))
XMPPServer.client_id = ctl.get('admin') XMPPServer.client_id = ctl.get('admin')
return return
#forward #forward
for client in XMPPServer.clients: for client in XMPPServer.clients:
@ -275,9 +275,9 @@ class Client(threading.Thread):
client.send(data.decode('utf-8')) client.send(data.decode('utf-8'))
except Exception as e: except Exception as e:
xmppserverlog.exception('{}'.format(e)) xmppserverlog.exception('{}'.format(e))
def _handle_result(self, data): def _handle_result(self, data):
# forward # forward
try: try:
for client in XMPPServer.clients: for client in XMPPServer.clients:
@ -286,11 +286,11 @@ class Client(threading.Thread):
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))
def _handle_connect(self, data): def _handle_connect(self, data):
try: try:
if self.state == self.CONNECT: if self.state == self.CONNECT:
#Client first connecting, send our features #Client first connecting, send our features
@ -302,15 +302,15 @@ class Client(threading.Thread):
#self.send('<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns:tls="http://www.ietf.org/rfc/rfc2595.txt" xmlns="jabber:client" version="1.0" id="1" from="{}">'.format(XMPPServer.server_id)) #self.send('<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns:tls="http://www.ietf.org/rfc/rfc2595.txt" xmlns="jabber:client" version="1.0" id="1" from="{}">'.format(XMPPServer.server_id))
time.sleep(0.25) time.sleep(0.25)
# send authentication support for iq-auth (fallback) and SASL # send authentication support for iq-auth (fallback) and SASL
self.send('<stream:features><auth xmlns="http://jabber.org/features/iq-auth"/><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism></mechanisms></stream:features>') self.send('<stream:features><auth xmlns="http://jabber.org/features/iq-auth"/><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism></mechanisms></stream:features>')
#self.send('<stream:features><auth xmlns="http://jabber.org/features/iq-auth"/></stream:features>') #self.send('<stream:features><auth xmlns="http://jabber.org/features/iq-auth"/></stream:features>')
elif data.decode('utf-8').find('jabber:iq:auth') > -1: #Handle iq-auth elif data.decode('utf-8').find('jabber:iq:auth') > -1: #Handle iq-auth
self._handle_iq_auth(data) self._handle_iq_auth(data)
elif data.decode('utf-8').find('urn:ietf:params:xml:ns:xmpp-sasl') > -1: #Handle SASL auth elif data.decode('utf-8').find('urn:ietf:params:xml:ns:xmpp-sasl') > -1: #Handle SASL auth
self._handle_sasl_auth(data) self._handle_sasl_auth(data)
elif self.state == self.INIT: elif self.state == self.INIT:
#Client getting session after authentication #Client getting session after authentication
if data.decode('utf-8').find('jabber:client') > -1: if data.decode('utf-8').find('jabber:client') > -1:
@ -318,34 +318,34 @@ class Client(threading.Thread):
self.send('<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" version="1.0" id="1" from="{}">'.format(XMPPServer.server_id)) self.send('<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" version="1.0" id="1" from="{}">'.format(XMPPServer.server_id))
time.sleep(0.25) time.sleep(0.25)
# session # session
self.send('<stream:features><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></stream:features>') self.send('<stream:features><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></stream:features>')
else: #Handle init bind else: #Handle init bind
xml = ET.fromstring(data.decode('utf-8')) xml = ET.fromstring(data.decode('utf-8'))
if len(xml): if len(xml):
child = self._tag_strip_uri(xml[0].tag) child = self._tag_strip_uri(xml[0].tag)
else: else:
child = None child = None
if xml.tag == 'iq': if xml.tag == 'iq':
if child == 'bind': if child == 'bind':
self._handle_bind(xml) self._handle_bind(xml)
except Exception as e: except Exception as e:
xmppserverlog.exception('{}'.format(e)) xmppserverlog.exception('{}'.format(e))
def _handle_iq_auth(self, data): def _handle_iq_auth(self, data):
try: try:
xml = ET.fromstring(data.decode('utf-8')) xml = ET.fromstring(data.decode('utf-8'))
ctl = xml[0][0] ctl = xml[0][0]
xmppserverlog.info("IQ AUTH XML: {}".format(xml)) xmppserverlog.info("IQ AUTH XML: {}".format(xml))
#Received username and auth tag, send username/password requirement #Received username and auth tag, send username/password requirement
if xml.get('type') == 'get' and "auth}username" in ctl.tag and self.type == self.UNKNOWN: if xml.get('type') == 'get' and "auth}username" in ctl.tag and self.type == self.UNKNOWN:
self.send('<iq type="result" id="{}"><query xmlns="jabber:iq:auth"><username/><password/></query></iq>'.format(xml.get('id'))) self.send('<iq type="result" id="{}"><query xmlns="jabber:iq:auth"><username/><password/></query></iq>'.format(xml.get('id')))
#Received username, password, resource - Handle auth here and return pass or fail #Received username, password, resource - Handle auth here and return pass or fail
if xml.get('type') == 'set' and "auth}username" in ctl.tag and self.type == self.UNKNOWN: if xml.get('type') == 'set' and "auth}username" in ctl.tag and self.type == self.UNKNOWN:
xmlauth = xml[0].getchildren() xmlauth = xml[0].getchildren()
uid = '' uid = ''
password = '' password = ''
@ -353,7 +353,7 @@ class Client(threading.Thread):
for aitem in xmlauth: for aitem in xmlauth:
if 'username' in aitem.tag: if 'username' in aitem.tag:
self.uid = aitem.text self.uid = aitem.text
elif 'password' in aitem.tag: elif 'password' in aitem.tag:
password = aitem.text.split("/")[2] password = aitem.text.split("/")[2]
authcode = password authcode = password
@ -363,18 +363,18 @@ class Client(threading.Thread):
resource = self.clientresource resource = self.clientresource
if not self.uid.startswith("fuid"): if not self.uid.startswith("fuid"):
#Need sample data to see details here #Need sample data to see details here
bumper.add_bot('',self.uid, '', resource) bumper.add_bot('',self.uid, '', resource)
xmppserverlog.info("bot authenticated {}".format(self.uid)) xmppserverlog.info("bot authenticated {}".format(self.uid))
#Client authenticated, move to next state #Client authenticated, move to next state
self._set_state('INIT') self._set_state('INIT')
#Successful auth #Successful auth
self.send('<iq type="result" id="{}"/>'.format(xml.get('id'))) self.send('<iq type="result" id="{}"/>'.format(xml.get('id')))
else: else:
auth = False auth = False
if bumper.check_authcode(self.uid, authcode): if bumper.check_authcode(self.uid, authcode):
auth = True auth = True
@ -382,34 +382,34 @@ class Client(threading.Thread):
auth = True auth = True
if auth: if auth:
bumper.add_client(self.uid, 'bumper', self.clientresource) bumper.add_client(self.uid, 'bumper', self.clientresource)
xmppserverlog.debug("client authenticated {}".format(self.uid)) xmppserverlog.debug("client authenticated {}".format(self.uid))
#Client authenticated, move to next state #Client authenticated, move to next state
self._set_state('INIT') self._set_state('INIT')
#Successful auth #Successful auth
self.send('<iq type="result" id="{}"/>'.format(xml.get('id'))) self.send('<iq type="result" id="{}"/>'.format(xml.get('id')))
else: else:
#Failed auth #Failed auth
self.send('<iq type="error" id="{}"><error code="401" type="auth"><not-authorized xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>'.format(xml.get('id'))) self.send('<iq type="error" id="{}"><error code="401" type="auth"><not-authorized xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>'.format(xml.get('id')))
except ET.ParseError as e: except ET.ParseError as e:
if "no element found" in e.msg: if "no element found" in e.msg:
xmppserverlog.debug('xml parse error - {} - {} - this is common with ecovac protocol'.format(data.decode('utf-8'), e)) xmppserverlog.debug('xml parse error - {} - {} - this is common with ecovac protocol'.format(data.decode('utf-8'), e))
elif "not well-formed (invalid token)" in e.msg: elif "not well-formed (invalid token)" in e.msg:
xmppserverlog.debug('xml parse error - {} - {}'.format(data.decode('utf-8'), e)) xmppserverlog.debug('xml parse error - {} - {}'.format(data.decode('utf-8'), e))
else: else:
xmppserverlog.debug('xml parse error - {} - {}'.format(data.decode('utf-8'), e)) xmppserverlog.debug('xml parse error - {} - {}'.format(data.decode('utf-8'), e))
except Exception as e: except Exception as e:
xmppserverlog.exception('{}'.format(e)) xmppserverlog.exception('{}'.format(e))
def _handle_sasl_auth(self, data): def _handle_sasl_auth(self, data):
try: try:
xml = ET.fromstring(data.decode('utf-8')) xml = ET.fromstring(data.decode('utf-8'))
saslauth = base64.b64decode(xml.text).decode('utf-8').split("/") saslauth = base64.b64decode(xml.text).decode('utf-8').split("/")
username = saslauth[0] username = saslauth[0]
username = saslauth[0].split('\x00')[1] username = saslauth[0].split('\x00')[1]
@ -420,15 +420,15 @@ class Client(threading.Thread):
if not self.uid.startswith("fuid"): if not self.uid.startswith("fuid"):
#Need sample data to see details here #Need sample data to see details here
bumper.add_bot('',self.uid, '', resource) bumper.add_bot('',self.uid, '', resource)
xmppserverlog.info("bot authenticated {}".format(self.uid)) xmppserverlog.info("bot authenticated {}".format(self.uid))
#Send response #Send response
self.send('<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>') #Success self.send('<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>') #Success
#Client authenticated, move to next state #Client authenticated, move to next state
self._set_state('INIT') self._set_state('INIT')
else: else:
auth = False auth = False
if bumper.check_authcode(self.uid, authcode): if bumper.check_authcode(self.uid, authcode):
auth = True auth = True
@ -436,35 +436,35 @@ class Client(threading.Thread):
auth = True auth = True
if auth: if auth:
bumper.add_client(self.uid, 'bumper', self.clientresource) bumper.add_client(self.uid, 'bumper', self.clientresource)
xmppserverlog.debug("client authenticated {}".format(self.uid)) xmppserverlog.debug("client authenticated {}".format(self.uid))
#Client authenticated, move to next state #Client authenticated, move to next state
self._set_state('INIT') self._set_state('INIT')
#Send response #Send response
self.send('<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>') #Success self.send('<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>') #Success
else: else:
#Failed to authenticate #Failed to authenticate
self.send('<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>') #Fail self.send('<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>') #Fail
except ET.ParseError as e: except ET.ParseError as e:
if "no element found" in e.msg: if "no element found" in e.msg:
xmppserverlog.debug('xml parse error - {} - {} - this is common with ecovac protocol'.format(data.decode('utf-8'), e)) xmppserverlog.debug('xml parse error - {} - {} - this is common with ecovac protocol'.format(data.decode('utf-8'), e))
elif "not well-formed (invalid token)" in e.msg: elif "not well-formed (invalid token)" in e.msg:
xmppserverlog.debug('xml parse error - {} - {}'.format(data.decode('utf-8'), e)) xmppserverlog.debug('xml parse error - {} - {}'.format(data.decode('utf-8'), e))
else: else:
xmppserverlog.debug('xml parse error - {} - {}'.format(data.decode('utf-8'), e)) xmppserverlog.debug('xml parse error - {} - {}'.format(data.decode('utf-8'), e))
except Exception as e: except Exception as e:
xmppserverlog.exception('{}'.format(e)) xmppserverlog.exception('{}'.format(e))
def _handle_bind(self, xml): def _handle_bind(self, xml):
try: try:
bumper_bots = self.bumper_bots.get() bumper_bots = self.bumper_bots.get()
bumper_clients = self.bumper_clients.get() bumper_clients = self.bumper_clients.get()
for bot in bumper_bots: for bot in bumper_bots:
if self.uid == bot.did: if self.uid == bot.did:
bot.xmpp_connection = True bot.xmpp_connection = True
@ -474,7 +474,7 @@ class Client(threading.Thread):
for client in bumper_clients: for client in bumper_clients:
if self.uid == client.userid: if self.uid == client.userid:
client.xmpp_connection = True client.xmpp_connection = True
#xmppserverlog.info("client connected {}".format(client.userid)) #xmppserverlog.info("client connected {}".format(client.userid))
self.bumper_clients.set(bumper_clients) self.bumper_clients.set(bumper_clients)
clientbindxml = xml.getchildren() clientbindxml = xml.getchildren()
@ -487,15 +487,15 @@ class Client(threading.Thread):
else: else:
xmppserverlog.debug("new client {}".format(self.address)) xmppserverlog.debug("new client {}".format(self.address))
res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format(xml.get('id'), XMPPServer.bot_id) res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format(xml.get('id'), XMPPServer.bot_id)
self._set_state('BIND') self._set_state('BIND')
self.send(res) self.send(res)
except Exception as e: except Exception as e:
xmppserverlog.exception('{}'.format(e)) xmppserverlog.exception('{}'.format(e))
def _handle_session(self, xml): def _handle_session(self, xml):
try: try:
res = '<iq type="result" id="{}" />'.format(xml.get('id')) res = '<iq type="result" id="{}" />'.format(xml.get('id'))
self._set_state('READY') self._set_state('READY')
self.send(res) self.send(res)
@ -503,59 +503,60 @@ class Client(threading.Thread):
except Exception as e: except Exception as e:
xmppserverlog.exception('{}'.format(e)) xmppserverlog.exception('{}'.format(e))
def _handle_presence(self, xml): def _handle_presence(self, xml):
try: try:
if len(xml) and xml[0].tag == 'status': if len(xml) and xml[0].tag == 'status':
# bot announcing arrival # bot announcing arrival
self.type = self.BOT self.type = self.BOT
xmppserverlog.debug('{} type set to BOT (based on presence tag)'.format(self.address)) xmppserverlog.debug('{} type set to BOT (based on presence tag)'.format(self.address))
# send a command from an unknown user - the response will contain the correct admin username # send a command from an unknown user - the response will contain the correct admin username
self.send('<iq type="set" id="{}" from="{}" to="{}"><query xmlns="com:ctl"><ctl td="GetCleanState" /></query></iq>'.format(uuid.uuid4(), 'unknown@ecouser.net', XMPPServer.bot_id)) self.send('<iq type="set" id="{}" from="{}" to="{}"><query xmlns="com:ctl"><ctl td="GetCleanState" /></query></iq>'.format(uuid.uuid4(), 'unknown@ecouser.net', XMPPServer.bot_id))
else: else:
self.type = self.CONTROLLER self.type = self.CONTROLLER
xmppserverlog.debug('{} type set to CONTROLLER (based on presence tag)'.format(self.address)) xmppserverlog.debug('{} type set to CONTROLLER (based on presence tag)'.format(self.address))
self.send('<presence to="{}@{}/{}"> dummy </presence>'.format(self.uid, XMPPServer.bot_id, self.clientresource)) self.send('<presence to="{}@{}/{}"> dummy </presence>'.format(self.uid, XMPPServer.bot_id, self.clientresource))
except Exception as e: except Exception as e:
xmppserverlog.exception('{}'.format(e)) xmppserverlog.exception('{}'.format(e))
def _parse_data(self, data): def _parse_data(self, data):
if self.log_incoming_data: if self.log_incoming_data:
xmppserverlog.debug('from {} - {}'.format(self.address, data.decode('utf-8'))) xmppserverlog.debug('from {} - {}'.format(self.address, data.decode('utf-8')))
try: try:
xml = ET.fromstring(data.decode('utf-8')) xml = ET.fromstring(data.decode('utf-8'))
self._handle_xml(xml, data) self._handle_xml(xml, data)
except ET.ParseError as e: except ET.ParseError as e:
if "no element found" in e.msg: #Element not closed or not all bytes received if "no element found" in e.msg: #Element not closed or not all bytes received
#Happens wth connect stream often #Happens wth connect stream often
if '<stream:stream ' in data.decode('utf-8'): if '<stream:stream ' in data.decode('utf-8'):
if self.state == self.CONNECT or self.state == self.INIT: if self.state == self.CONNECT or self.state == self.INIT:
self._handle_connect(data) self._handle_connect(data)
else: else:
xmppserverlog.error('xml parse error - {} - {}'.format(data.decode('utf-8'), e)) if not (data.decode('utf-8') == "" or data.decode('utf-8') == " "):
xmppserverlog.error('xml parse error - {} - {}'.format(data.decode('utf-8'), e))
elif "not well-formed (invalid token)" in e.msg: elif "not well-formed (invalid token)" in e.msg:
#If a lone </stream:stream> - client is signalling end of session/disconnect #If a lone </stream:stream> - client is signalling end of session/disconnect
if not '</stream:stream>' in data.decode('utf-8'): if not '</stream:stream>' in data.decode('utf-8'):
xmppserverlog.error('xml parse error - {} - {}'.format(data.decode('utf-8'), e)) xmppserverlog.error('xml parse error - {} - {}'.format(data.decode('utf-8'), e))
else: else:
self.send("</stream:stream>") #Close stream self.send("</stream:stream>") #Close stream
elif "junk after document element" in e.msg: #More than one xml doc in data elif "junk after document element" in e.msg: #More than one xml doc in data
#try to split it #try to split it
data0 = data.decode('utf-8') data0 = data.decode('utf-8')
data1 = data0[e.position[1]:] data1 = data0[e.position[1]:]
data0 = data0[:e.position[1]] data0 = data0[:e.position[1]]
#xmppserverlog.debug('xml parse error - {} - {} - split0: {} - split1: {}'.format(data.decode('utf-8'), e, data0, data1)) #xmppserverlog.debug('xml parse error - {} - {} - split0: {} - split1: {}'.format(data.decode('utf-8'), e, data0, data1))
self._parse_data(data0.encode('utf-8')) self._parse_data(data0.encode('utf-8'))
self._parse_data(data1.encode('utf-8')) self._parse_data(data1.encode('utf-8'))
else: else:
xmppserverlog.debug('xml parse error - {} - {}'.format(data.decode('utf-8'), e)) xmppserverlog.debug('xml parse error - {} - {}'.format(data.decode('utf-8'), e))
except Exception as e: except Exception as e:
xmppserverlog.exception('{}'.format(e)) xmppserverlog.exception('{}'.format(e))
@ -563,29 +564,29 @@ class Client(threading.Thread):
def _handle_xml(self, xml, data): def _handle_xml(self, xml, data):
try: try:
if self.state == self.CONNECT or self.state == self.INIT: if self.state == self.CONNECT or self.state == self.INIT:
self._handle_connect(data) self._handle_connect(data)
if len(xml): if len(xml):
child = self._tag_strip_uri(xml[0].tag) child = self._tag_strip_uri(xml[0].tag)
else: else:
child = None child = None
if xml.tag == 'iq': if xml.tag == 'iq':
if child == 'bind': if child == 'bind':
self._handle_bind(xml) self._handle_bind(xml)
elif child == 'session': elif child == 'session':
self._handle_session(xml) self._handle_session(xml)
elif child == 'query': elif child == 'query':
self._handle_ctl(xml, data) self._handle_ctl(xml, data)
elif child == 'ping': elif child == 'ping':
self._handle_ping(xml, data) self._handle_ping(xml, data)
elif xml.get('type') == 'result': elif xml.get('type') == 'result':
self._handle_result(data) self._handle_result(data)
elif xml.tag == 'presence': elif xml.tag == 'presence':
self._handle_presence(xml) self._handle_presence(xml)
except Exception as e: except Exception as e:
xmppserverlog.exception('{}'.format(e)) xmppserverlog.exception('{}'.format(e))
def run(self): def run(self):
@ -601,12 +602,12 @@ class Client(threading.Thread):
data = self.connection.recv(4096) data = self.connection.recv(4096)
except ConnectionResetError as e: except ConnectionResetError as e:
xmppserverlog.error('{}'.format(e)) xmppserverlog.error('{}'.format(e))
except OSError as e: except OSError as e:
xmppserverlog.error('{}'.format(e)) xmppserverlog.error('{}'.format(e))
except Exception as e: except Exception as e:
xmppserverlog.exception('{}'.format(e)) xmppserverlog.exception('{}'.format(e))
if data != b'': if data != b'':
self._parse_data(data) self._parse_data(data)