class NodoNaranja: # Aqui se ponen los detalles para ajusta puerto y IP def __init__(self, routingTableDir, dirGrafoAzul, timeout, ID): self.rand = random self.ip = '0.0.0.0' self.routingTable = RoutingTable(routingTableDir) self.colaEntrada = queue.Queue() self.colaSalida = queue.Queue() self.diccionariosACKs = { } # { SNRN_1:{1:'', 2:'', 3:'', 4:'', 5:''}, SNRN_2:{1:'', 2:'', 3:'', 4:'', 5:''}, SNRN_N:{1:'', 2:'', 3:'', 4:'', 5:''}} self.SNRN = self.rand.randrange(65536) self.secure_UDP = 0 self.port = 0000 self.nodeID = ID self.tablaNodosAzules = TablaNodosAzules(dirGrafoAzul) self.TIMEOUT = timeout self.semaphore = threading.Semaphore(0) self.timeStamp = time.time() self.blueNodesAsignedByMe = {} def nextSNRN(self, SNRN): next = (SNRN + 1) % 65536 return next def run(self): for i in self.routingTable.table: if i.getNode() == self.nodeID: #print(i.print_data()) self.ip = i.getIp() self.port = i.getPort() self.secure_UDP = USL(self.ip, self.port, self.TIMEOUT) t6 = threading.Thread(target=self.secure_UDP.run) t6.start() # Hilos recibidor t = threading.Thread(target=self.HiloRecibidor) t.start() # print("hilo recibidor iniciado") # hilo timeouts t3 = threading.Thread(target=self.HiloTimeOuts) t3.start() # hilo enviador t4 = threading.Thread(target=self.HiloEnviador) t4.start() # print(("hilo enviador iniciado")) # hilo logico t5 = threading.Thread(target=self.HiloLogico) t5.start() # print("hilo logico iniciado") def clearAcks(self, acks, max): acks.clear() for i in range(max): if (i != self.nodeID): acks[i] = '' return acks def HiloTimeOuts(self): while True: #print("Time stamp: ", self.timeStamp - time.time() ) if time.time() - self.timeStamp > self.TIMEOUT: #print("TAMAÑO DE LA COLA A ENVIAR: ", len(self.cola_enviar)) if not self.colaSalida.empty(): self.semaphore.release() self.timeStamp = time.time() def HiloRecibidor(self): while True: #print("estoy a punto de recibir un paquete en el hilo recibidor") payload, client_address = self.secure_UDP.recibir( ) # recibe 1035 bytes y la (direcciónIP, puerto) del origen #print("recibí el paquete: ", payload) #payload, client_address = self.sock.recvfrom(1035) # recibe 1035 bytes y la (direcciónIP, puerto) del origen tipo = int.from_bytes(payload[:1], byteorder=('little')) if tipo == 0: # caso 1 narnja naranja targetNode = int.from_bytes(payload[9:10], byteorder=('little')) # destino #print("Es para: ", targetNode) #print("Yo soy: ", self.nodeID) if targetNode == self.nodeID: self.colaEntrada.put(payload) # If not then just put it to the outputQueue else: self.colaSalida.put(payload) ##narnaja azul elif tipo == 1: paquete = n_aPaq() paquete = paquete.unserialize(payload) paquete.ipAzul = client_address[ 0] # para poder responderle necesito la IP paquete.puertoAzul = client_address[1] # y el puerto # sin embargo ambas cosas vienen con el mensaje que me mandó. #paquete.imprimir() payload = paquete.serialize() self.colaEntrada.put(payload) def HiloEnviador(self): while True: self.semaphore.acquire() ##Takes a package from the queue. If the queue is empty it waits until a package arrives while not self.colaSalida.empty(): bytePacket = self.colaSalida.get() tipo = int.from_bytes(bytePacket[:1], byteorder='little') # si es para naranjas if tipo == 0: # Orange & Orange ##BYTE 9 has the orangetarget targetNode = int.from_bytes(bytePacket[9:10], byteorder='little') # Routing_table returns the address address = self.routingTable.retrieveAddress(targetNode) try: self.secure_UDP.send(bytePacket, address[0], address[1]) except OSError as err: print("Failed on addressing: ", err) # si es para azules elif tipo == 1: # si es azul bluepack = n_aPaq() bluepack = bluepack.unserialize(bytePacket) blueIp = bluepack.ipAzul bluePort = bluepack.puertoAzul self.secure_UDP.send(bytePacket, blueIp, bluePort) def HiloLogico(self): # print("This is a blue to orange pack, still needs the implementation") # paq = n_nPaq(1,0,0,0,'d',0,'0.0.0.0',0,0) # test=colaEntrada.get()#saca de cola # paq.unserialize(test);#ya puede usar paq para todo # print(paq.puertoAzul) puertoAzul = 8888 ipAzul = "0.0.0.0" nodoSolicitado = 350 snSolicitud = 0 prioridad = 500 acks = { } # diccionario para acks que utiliza el ID del nodo naranja para ver en si está ack'd o no. Esto se debe apendizar con el SNRN del paquete de solicitud como llave al self.diccionariosACKs ganeNodo = False acks_Write = {} acks_Write_Done = False MAX_NODOS_NARANJA = 4 procesando_solicitud_azul = False graphComplete = False workDone = False acks = self.clearAcks(acks, MAX_NODOS_NARANJA) #print(acks) while True: if not self.colaEntrada.empty(): packet = self.colaEntrada.get() #print("Paquete obtenido en hilo logico") tipo = int.from_bytes(packet[:1], byteorder=('little')) if tipo == 0: #print("el paquete es naranja-naranja") package = n_nPaq(0, self.nodeID, self.nodeID, self.nodeID, '', 0, "0.0.0.0", 5000, 0) package = package.unserialize(packet) #print(package.categoria, package.sn, package.origenNaranja, package.destinoNaranja, package.puertoAzul, # package.ipAzul, str(package.tipo), package.posGrafo, package.prioridad) if package.tipo == b'r': # Request de un pquete (solicitud) #print("Packet request from: ", package.origenNaranja, " pidiendo el numero: ", package.posGrafo, # " con la prioridad: ", package.prioridad) if package.posGrafo == nodoSolicitado: # yo pedi ese mismo nodo y por tanto hay conflicto if package.prioridad < prioridad: # yo gano el conflicto #print("Gané la batalla por el nodo ", nodoSolicitado, " (My ID: ", self.nodeID, # " Mi prioridad: ", # prioridad, ") (La ID del otro: ", package.origenNaranja, " La prioridad del otro: ", # package.prioridad, ")") negacion = n_nPaq(0, package.sn, self.nodeID, package.origenNaranja, 'd', package.posGrafo, package.ipAzul, package.puertoAzul, package.prioridad) negacion_bytes = negacion.serialize() self.colaSalida.put(negacion_bytes) elif package.prioridad > prioridad: # yo pierdo el conflicto #print("Perdí la batalla por el nodo ", nodoSolicitado, " (My ID: ", self.nodeID, " Mi prioridad: ", # prioridad, ") (La ID del otro: ", package.origenNaranja, " La prioridad del otro: ", package.prioridad, ")") accept = n_nPaq(0, package.sn, self.nodeID, package.origenNaranja, 'a', package.posGrafo, package.ipAzul, package.puertoAzul, package.prioridad) accept_bytes = accept.serialize() self.colaSalida.put(accept_bytes) else: # empatamos con prioridad #print("Empatamos la batalla por el nodo ", nodoSolicitado, " (My ID: ", self.nodeID," Mi prioridad: ", # prioridad, ") (La ID del otro: ", package.origenNaranja, " La prioridad del otro: ", package.prioridad, ")") if self.nodeID > package.origenNaranja: # lo resolvemos con ip y gano # print("Gané la batalla por el nodo ", nodoSolicitado, " (My ID: ", self.nodeID, " Mi prioridad: ", # prioridad, ") (La ID del otro: ", package.origenNaranja, " La prioridad del otro: ", package.prioridad, ")") negacion = n_nPaq( 0, package.sn, self.nodeID, package.origenNaranja, 'd', package.posGrafo, package.ipAzul, package.puertoAzul, package.prioridad) negacion_bytes = negacion.serialize() self.colaSalida.put(negacion_bytes) else: # perdí por ip # print("Perdí la batalla por el nodo ", nodoSolicitado, " (My ID: ", self.nodeID, " Mi prioridad: ", # prioridad, ") (La ID del otro: ", package.origenNaranja," La prioridad del otro: ", # package.prioridad, ")") accept = n_nPaq(0, package.sn, self.nodeID, package.origenNaranja, 'a', package.posGrafo, package.ipAzul, package.puertoAzul, package.prioridad) accept_bytes = accept.serialize() self.colaSalida.put(accept_bytes) else: # yo no pedí ese nodo #print("No hay batalla por el nodo ", nodoSolicitado, " (My ID: ", self.nodeID, " Mi prioridad: ", # prioridad, ") (La ID del otro: ", package.origenNaranja, " La prioridad del otro: ", package.prioridad, ")") self.tablaNodosAzules.marcarComoSolicitado( package.posGrafo) accept = n_nPaq(0, package.sn, self.nodeID, package.origenNaranja, 'a', package.posGrafo, package.ipAzul, package.puertoAzul, package.prioridad) accept_bytes = accept.serialize() self.colaSalida.put(accept_bytes) elif package.tipo == b'a': print("Recibi un accept por el nodo naranja ", package.origenNaranja, " Sobre mi pedido: ", package.posGrafo, " De parte del nodo azul: ", package.ipAzul, "Con SNRN: ", package.sn) if package.posGrafo == nodoSolicitado: # agrega el ack al mapa de acks. lo voy a explicar arriba. # print(self.diccionariosACKs) if package.sn in self.diccionariosACKs: self.diccionariosACKs[package.sn][ package. origenNaranja] = 'a' # del diccionario con llave = sn, en el lugar con llave origenNaranja, ponga el accept. #print("EL ORIGEN NARANJA ES: ", package.origenNaranja) #print(self.diccionariosACKs[package.sn][package.origenNaranja]) else: print( "Es un ack de un paquete anterior al actual" ) #print(self.diccionariosACKs) #if len(self.diccionariosACKs[package.sn]) == MAX_NODOS_NARANJA - 1: #esto hay que cambiarlo porque creo que el diccionario siepmre va a tener 5 elementos #acks_done = True #print("recibi todos los acks de la petición: ", nodoSolicitado) elif package.tipo == b'd': print("Recibi un decline por el nodo naranja ", package.origenNaranja, " Sobre mi pedido: ", nodoSolicitado, " De parte del nodo azul: ", ipAzul, " Con SNRN: ", package.sn) if package.posGrafo == nodoSolicitado: # si recibí un decliene significa que perdí la batalla por el nodo por lo que tengo que iniciar una nueva. self.diccionariosACKs.clear() acks = self.clearAcks(acks, MAX_NODOS_NARANJA) nodoSolicitado = self.tablaNodosAzules.getNodoDisponible( ) self.tablaNodosAzules.marcarComoSolicitado( nodoSolicitado) # print("Dado que perdí el nodo: ", package.posGrafo, " me veo en la obligación de cambiar por: ", nodoSolicitado) prioridad = self.rand.randrange(0, 4294967296) self.diccionariosACKs[self.SNRN] = acks # print(self.diccionariosACKs) # print("Nodos disponibles ", end='') self.tablaNodosAzules.printNodosDisponibles() snSolicitud = self.SNRN for i in self.routingTable.table: if not i.getNode() == self.nodeID: request = n_nPaq(0, self.SNRN, self.nodeID, i.getNode(), 'r', nodoSolicitado, ipAzul, puertoAzul, prioridad) request = request.serialize() self.colaSalida.put(request) self.SNRN = self.nextSNRN( self.SNRN ) # avanzo el SN para ponerle uno distinto al siguiente paquete de datos. # esto significa que perdí el paquete por lo que tengo que detener la espera de acks. elif package.tipo == b'w': print("Recibi un Write de parte del nodo naranja: ", package.origenNaranja, " Sobre el nodo: ", package.posGrafo) direccion = (package.ipAzul, package.puertoAzul) self.tablaNodosAzules.write(package.posGrafo, direccion) saved_packet = n_nPaq(0, self.SNRN, self.nodeID, package.origenNaranja, 's', package.posGrafo, package.ipAzul, package.puertoAzul, package.prioridad) self.SNRN = self.nextSNRN(self.SNRN) saved_packet = saved_packet.serialize() self.colaSalida.put(saved_packet) # write_ack = n_nPaq(0, sn, nodeID, package.origenNaranja, 's', posGrafo, ipAzul, puertoAzul, prioridad) # por definirse, mas los acks seguramente iran por secure UDP. elif package.tipo == b's': # Saved package print( "Recibi un Saved package de parte del nodo naranja: ", package.origenNaranja) if package.posGrafo == nodoSolicitado: acks_Write[package.origenNaranja] = 's' contador = 0 for i in acks_Write.keys(): contador += 1 if contador == MAX_NODOS_NARANJA - 1: acks_Write_Done = True elif tipo == 1: # el paquete es naranja-azul # cuerpo del naranja-azul if not procesando_solicitud_azul: # si no estoy procesando una solicitud azul entonces puedo proceder #print("Comunicación naranja-azul") bluePacket = n_aPaq() bluePacket = bluePacket.unserialize(packet) #print("Paquete de tipo: ", bluePacket.tipo) if bluePacket.tipo == 14: # es un paquete de solicitud. if len(self.tablaNodosAzules.nodosDisponibles ) != 0: ipAzul = bluePacket.ipAzul puertoAzul = bluePacket.puertoAzul #print("Es un paquete de solicitud azul con IP: ", str(ipAzul), " y puerto: ", puertoAzul) nodoSolicitado = self.tablaNodosAzules.getNodoDisponible( ) #nodoSolicitado = 4 #self.SNRN = 0 self.tablaNodosAzules.marcarComoSolicitado( nodoSolicitado) #print("Nodo solicitado: ", nodoSolicitado) prioridad = self.rand.randrange(0, 4294967296) self.diccionariosACKs[self.SNRN] = acks # print(self.diccionariosACKs) snSolicitud = self.SNRN for i in self.routingTable.table: if not i.getNode() == self.nodeID: request = n_nPaq( 0, self.SNRN, self.nodeID, i.getNode(), 'r', nodoSolicitado, i.getIp(), i.getPort(), prioridad) request = request.serialize() self.colaSalida.put(request) self.SNRN = self.nextSNRN( self.SNRN ) # avanzo el SN para ponerle uno distinto al siguiente paquete de datos. procesando_solicitud_azul = True else: print( "Solicitud rechazada: ya no hay más nodos azules disponibles en el grafo" ) else: # si ya estaba procesando una solicitud entonces devuelvo el paquete a la cola. #print("me llegó una solicitud mientras proceso otra, devolví la solicitud a la cola.") self.colaEntrada.put(packet) # bluePacket.imprimir() # procesar una solicitud: # almacenar el ip y el puerto del nodo, ya # generar un paquete de request con el número de nodo del grafo que elegí. ya # hacer un broadcast con ese paquete utilizando la tabla de rutamiento, ya # generar el diccionario de acks para este nodo, ya # OBS: Tengo que asignar un SN a la petición y utilizar el mismo SN para diccionariosACKs ya # if procesando_solicitud_azul: # print("entré en procesando solicitud") countingACKs = 0 for i in range(MAX_NODOS_NARANJA): if not i == self.nodeID: if self.diccionariosACKs[snSolicitud][i] == 'a': countingACKs += 1 if countingACKs == MAX_NODOS_NARANJA - 1: ganeNodo = True # print(self.diccionariosACKs) #print(ganeNodo) if ganeNodo: #print("entré en gané nodo") vecinos_azules = [] for i in self.tablaNodosAzules.grafoNodosAzules[ nodoSolicitado]: vecinos_azules.append(i) # print(vecinos_azules) self.tablaNodosAzules.write(nodoSolicitado, (ipAzul, puertoAzul)) respuesta_azul = n_aPaq(1, self.SNRN, 15, nodoSolicitado, str(ipAzul), puertoAzul, vecinos_azules) self.SNRN = self.nextSNRN(self.SNRN) # respuesta_azul.imprimir() respuesta_azul = respuesta_azul.serialize() self.colaSalida.put(respuesta_azul) for i in self.routingTable.table: if not i.getNode() == self.nodeID: write_package = n_nPaq(0, self.SNRN, self.nodeID, i.getNode(), 'w', nodoSolicitado, str(ipAzul), puertoAzul, prioridad) # write_package.imprimir() write_package = write_package.serialize() self.colaSalida.put(write_package) self.blueNodesAsignedByMe[nodoSolicitado] = (str(ipAzul), puertoAzul) self.SNRN = self.nextSNRN(self.SNRN) ganeNodo = False acks = self.clearAcks(acks, MAX_NODOS_NARANJA) if acks_Write_Done: #print("entré en write acks done") procesando_solicitud_azul = False nodoSolicitado = -1 ipAzul = '0.0.0.0' puertoAzul = 0000 acks_Write.clear() acks_Write_Done = False if len(self.tablaNodosAzules.nodosDisponibles ) == 0 and not workDone and ( self.tablaNodosAzules.cantidadAsignados == self.tablaNodosAzules.cantidadNodos): if not procesando_solicitud_azul and not graphComplete and self.colaEntrada.empty( ) and self.colaSalida.empty(): for i in self.blueNodesAsignedByMe.keys(): respuesta_azul = n_aPaq( 1, self.SNRN, 16, i, self.blueNodesAsignedByMe[i][0], self.blueNodesAsignedByMe[i][1], self.tablaNodosAzules.getListaVecinos(i)) self.SNRN = self.nextSNRN(self.SNRN) # print(self.tablaNodosAzules.getListaVecinos(i)) respuesta_azul = respuesta_azul.serialize() self.colaSalida.put(respuesta_azul) graphComplete = True if graphComplete and self.colaEntrada.empty( ) and self.colaSalida.empty() and not workDone: for i in self.blueNodesAsignedByMe.keys(): paqGraphComplete = n_aPaq( 1, self.SNRN, 17, i, self.blueNodesAsignedByMe[i][0], self.blueNodesAsignedByMe[i][1], self.tablaNodosAzules.getListaVecinos(i)) self.SNRN = self.nextSNRN(self.SNRN) paqGraphComplete = paqGraphComplete.serialize() self.colaSalida.put(paqGraphComplete) workDone = True