Skip to content

Instantly share code, notes, and snippets.

@dpineiden
Last active July 20, 2016 20:02
Show Gist options
  • Save dpineiden/5b8b4a2378503dca89e41a6dd8a93541 to your computer and use it in GitHub Desktop.
Save dpineiden/5b8b4a2378503dca89e41a6dd8a93541 to your computer and use it in GitHub Desktop.
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