Last active
July 20, 2016 20:02
-
-
Save dpineiden/5b8b4a2378503dca89e41a6dd8a93541 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio, asyncssh, sys | |
#PASS DICT TO STTRING | |
import json | |
import copy | |
""" | |
Este método es para generar un identificador único para distintas instancias | |
durante el tiempo de operación del servidor | |
""" | |
import uuid | |
def my_random_string(string_length=10): | |
"""Returns a random string of length string_length.""" | |
random = str(uuid.uuid4()) # Convert UUID format to a Python string. | |
random = random.upper() # Make all characters uppercase. | |
random = random.replace("-","") # Remove the UUID '-'. | |
return random[0:string_length] # Return the random string. | |
#str(my_random_string(6)) | |
#print(my_random_string(6)) # For example, D9E50C | |
class MySSHServerSession(asyncssh.SSHServerSession): | |
SESSION = {} | |
CHANNEL = {} | |
COMMANDS = dict( | |
SYNCCLIENT=dict( | |
desc="Se sincroniza id session con id de cliente", | |
code="IDX|ID|CLIENTID", | |
), | |
SESSIONLST=dict( | |
desc="Se envía lista de sesiones activas en servidor a cliente", | |
code='IDX|GET|LST|CLIENTID', | |
), | |
COMMANDLST=dict( | |
desc="Se envía la lista de comandos que soporta servidor en atención a cliente", | |
code='IDX|GET|LST|CMD|ID' | |
), | |
SENDMSG1=dict( | |
desc="Se envía mensaje a un solo destinatario", | |
code='IDX|SND|MSG|UNIQ|CLID|MYID|MSG_DATA' | |
), | |
SENDMSGALL=dict( | |
desc="Se envía mensaje a todos", | |
code='IDX|SND|MSG|ALL|CLID|MSG_DATA' | |
), | |
SENDMSGGRP=dict( | |
desc="Se envía mensajes a grupo seleccionado", | |
code='IDX|SND|MSG|GRP|CLID|MSG_DATA' | |
) | |
) | |
#identificador de session: | |
#Debe contener una lista de sesiones | |
#idx = [] | |
def __init__(self, uin=6): | |
self._input = '' | |
self._total = 0 | |
self.uin = uin | |
self.client_id='' | |
#Esto está bien si y solo si en la creacion de nuevas instancias no se modifica el uin | |
#de otra manera sería necesario reiniciar servidor | |
for k in MySSHServerSession.COMMANDS.keys(): | |
c_length=0 | |
plecas=MySSHServerSession.COMMANDS[k]['code'].count('|') | |
if k=='SYNCCLIENT': | |
c_length = self.uin+plecas+2 | |
elif k=='SESSIONLST': | |
c_length = self.uin+plecas+3+3 | |
elif k=='COMMANDLST': | |
c_length = self.uin+plecas+3+3+3 | |
elif k=='SENDMSG1': | |
c_length = self.uin+plecas+3+3+4 | |
elif k=='SENDMSGALL': | |
c_length = self.uin+plecas+3+3+3 | |
elif k=='SENDMSGGRP': | |
c_length = self.uin+plecas+3+3+3 | |
MySSHServerSession.COMMANDS[k]['c_length'] = c_length | |
def connection_made(self, chan): | |
#called when channel is openned sucessfully SSHClientChannel | |
self._chan = chan | |
print (self._chan.get_extra_info('connection')) | |
print (self._chan.get_extra_info('local_peername')) | |
print (self._chan.get_extra_info('remote_peername')) | |
print (self._chan.get_extra_info('connection').get_extra_info('send_mac')) | |
#rint(self._chan) | |
print("Serversession") | |
#id_cl = len(MySSHServerSession.clients()) | |
(ip,port)=chan.get_extra_info('peername') | |
self.ip = ip | |
self.port=port | |
str_ip = "Tu ip es: "+ip+"\r\n" | |
self._chan.write(str_ip) | |
IDX = my_random_string(self.uin) | |
self.idx=IDX | |
print(IDX) | |
t = True | |
while t: | |
if IDX not in type(self).idx: | |
type(self).idx.append(IDX) | |
t=False | |
else: | |
IDX = my_random_string(6) | |
send_id = IDX+"|SND|ID\r\n" | |
self._chan.write(send_id) | |
def shell_requested(self): | |
return True | |
def exec_requested(self, command): | |
return True | |
def pty_requested(self, term_type, term_size, term_modes): | |
return True | |
def session_started(self): | |
self._chan.write("Bienvenid@ al servidor GNS!\r\n") | |
def data_received(self, data, datatype): | |
self._input += data.strip() | |
info = self._input.split('|') | |
print(info) | |
print("Recibiendo data:") | |
print("Nombre de Comando:") | |
print(info[0]) | |
print("Cliente Id:"+self.client_id) | |
if info[0] in MySSHServerSession.COMMANDS.keys() and info[1]==self.idx: | |
print(MySSHServerSession.COMMANDS[info[0]]) | |
print(info[0]) | |
c_length=MySSHServerSession.COMMANDS[info[0]]['c_length'] | |
print(c_length) | |
if info[1]==self.idx: | |
#SYNCCLIENT | |
#IDX|ID|CLIENTID | |
if info[0]=='SYNCCLIENT' and info[2]=='ID': | |
print("Se recibe ID") | |
self.client_id = info[3] | |
print(self.client_id) | |
self._chan.write(json.dumps(MySSHServerSession.SESSION)+"\r\n") | |
print("Agregando sesión") | |
MySSHServerSession.add_session(self.idx, self.client_id, self._chan, self.ip, self.port) | |
#SESSIONLST | |
#IDX|GET|LST|ID | |
elif info[0]=='SESSIONLST' and info[2]=='GET' and info[4]==self.client_id: | |
if info[3]=='LST': | |
print("enviando lista") | |
print(MySSHServerSession.SESSION) | |
info_x=self.idx+"|RCV|LST|"+json.dumps(MySSHServerSession.SESSION)+"\r\n" | |
MySSHServerSession.send_info(self.idx, info_x) | |
#COMMANDLST | |
#IDX|GET|LST|CMD|ID | |
elif info[0]=='COMMANDLST' and info[2]=='GET' and info[5]==self.client_id: | |
if info[3]=='LST' and info[4]=='CMD': | |
info_x=self.idx+"|RCV|LST|"+json.dumps(MySSHServerSession.COMMANDS)+"\r\n" | |
print(info_x) | |
MySSHServerSession.send_info(self.idx, info_x) | |
#SENDMSG1 | |
#IDX|SND|MSG|UNIQ|CLID|MYID|MSG_DATA | |
#MSG_DATA="VARNAME|DATA" | |
elif info[0]=='SENDMSG1' and info[2]=='SND' and info[3]=='MSG' and info[4]=='UNIQ' and info[5]==self.client_id: | |
#verificar si info[4] aún está disponible | |
try: | |
#Buscar en directorio el idx o key del elemento con client_id | |
client_id=info[6] | |
tot_length = c_length+len(client_id)+len(info[5]) | |
idx = MySSHServerSession.get_idx(client_id) | |
info_x=idx+"|RCV|MSG|"+self._input[tot_length::]+"\r\n" | |
MySSHServerSession.send_info(idx, info_x) | |
except: | |
MySSHServerSession.send_info(self.idx, "Ya no está conectado "+info[6]) | |
#SENDMSGALL | |
#IDX|SND|MSG|ALL|CLID|MSG_DATA | |
elif info[0]=='SENDMSGALL' and info[2]=='SND' and info[3]=='MSG' and info[4]=='ALL' and info[5]==self.client_id: | |
#verificar si info[5] aún está disponible | |
#Una lectura a la lista de sessiones y enviar por channel | |
tot_length = c_length+len(info[5]) | |
msg_data = self._input[tot_length::] | |
for k in MySSHServerSession.SESSION.keys(): | |
try: | |
#Crear msg: IDX RCV MSG DATA | |
idx = k | |
info_x = idx+"|RCV|MSG|"+msg_data+"\r\n" | |
MySSHServerSession.send_info(idx, info_x) | |
except: | |
MySSHServerSession.send_info(self.idx, "Ya no está conectado "+k) | |
#SENDMSGGRP | |
#IDX|SND|MSG|GRP|CLID|MSG_DATA | |
elif info[0]=='SENDMSGGRP' and info[2]=='SND' and info[3]=='MSG' and info[4]=='GRP' and info[5]==self.client_id: | |
#verificar si info[4] aún está disponible | |
#Tengo una lista definida de estaciones a las que deseo enviar un msg | |
#Esta lista esta definida por un string a|b|c|d | |
s_list = info[6].split() | |
tot_length = c_length+len(info[5]) | |
msg_data = self._input[tot_length::] | |
for s in s_list: | |
try: | |
client_id=s | |
idx = MySSHServerSession.get_idx(client_id) | |
info_x=idx+"|RCV|MSG|"+msg_data+"\r\n" | |
MySSHServerSession.send_info(idx, info_x) | |
except: | |
MySSHServerSession.send_info(self.idx, "Ya no está conectado "+s) | |
else: | |
MySSHServerSession.send_info(self.idx, "Tu comando no se reconoce") | |
self._input='' | |
def eof_received(self): | |
self._chan.write('Total = %s\r\n' % self._total) | |
#self._chan.exit(0) | |
def get_id(self): | |
return self.client_id | |
def connection_lost(self,exc): | |
try: | |
del type(self).SESSION[self.idx] | |
except: | |
print("Ni siquiera conectó cliente") | |
try: | |
del type(self).CHANNEL[self.idx] | |
except: | |
print("Ni siquiera conectó cliente") | |
@staticmethod | |
def get_idx(client_id): | |
W=MySSHServerSession.SESSION | |
for k, c in W.items(): | |
if c['id_cliente']==client_id: | |
idx=k | |
#podria ser mismo cliente con varias sesiones? | |
#manejar lista idx:futuro | |
break | |
return idx | |
@staticmethod | |
def send_info(chan_id, info): | |
print("Enviando"+info) | |
chan=MySSHServerSession.CHANNEL[chan_id] | |
chan.write(info) | |
@staticmethod | |
def add_session(idx, id_cl, chan, ip, port): | |
client_id = idx | |
client = dict( | |
id_cliente = id_cl, | |
ip = ip, | |
port = port | |
) | |
print(client) | |
print("Añadir") | |
MySSHServerSession.SESSION.update({client_id : client}) | |
MySSHServerSession.CHANNEL.update({client_id : chan}) | |
print("Añadido") | |
#print(MySSHServerSession.sessions()) | |
@staticmethod | |
def sessions(): | |
return MySSHServerSession.SESSION | |
class MySSHServer(asyncssh.SSHServer): | |
def session_requested(self): | |
print("Sesión: ") | |
self.session=MySSHServerSession() | |
#MySSHServer.add_session(self.id_cl,self.session,self.ip,self.port) | |
print(self.session) | |
#print(self.session._chan) | |
#print(self.session.client_id) | |
return self.session | |
def connection_made(self, connection): | |
self.connection = connection | |
print("server session") | |
print("Sesion PREVIA:") | |
print(connection) | |
print (connection.get_extra_info('peername')) | |
(ip,port)=connection.get_extra_info('peername') | |
self.ip=ip | |
self.port=port | |
print("end server chan") | |
#print (self._chan.get_extra_info('connection').get_extra_info('send_mac')) | |
#self.session.send_info('hola') | |
#print(self.session) | |
print(connection._server) | |
print(connection._channels) | |
print(connection._transport) | |
print(connection._owner) | |
print(connection._session_factory) | |
print(connection._protocol_factory) | |
#print(connection.send_debug("Probando msg", lang='es-ES')) | |
#connection.create_connection(MySSHServerSession,ip,port) | |
#print(self.session) | |
#session = connection.forward_connection(ip, int(port)) | |
#print(session) | |
#print(connection._session_factory._chan) | |
#self.session._chan.write(MySSHServer.clients()) | |
print("latter added clients") | |
#def connection_lost(self, exc): | |
#del type(self).SESSION[self.id] | |
async def start_server(): | |
#return a listener, with ._conn and ._session_factory | |
await asyncssh.create_server(MySSHServer, '', 8022, | |
server_host_keys=['/etc/ssh/ssh_host_dsa_key'], | |
authorized_client_keys='/home/david/.ssh/authorized_keys', | |
compression_algs=('zlib','[email protected]')) | |
loop = asyncio.get_event_loop() | |
try: | |
loop.run_until_complete(start_server()) | |
except (OSError, asyncssh.Error) as exc: | |
sys.exit('Error starting server: ' + str(exc)) | |
loop.run_forever() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment