def start_accepter(): global accepter_thread global affix_enabled global affix_stack_string global zenodotus_advertise_handle # do this until we get the accepter started... while True: if not node_reset_config['reset_accepter'] and is_accepter_started(): # we're done, return the name! return myname_port else: # If we came here because a reset was initiated, kill the old # accepter thread server socket before starting a new one. try: accepter_thread.close_serversocket() servicelogger.log( "Closed previous accepter thread server socket.") except: # There was no accepter_thread, or it couldn't .close_serversocket(). # No problem -- this means nothing will be in the way of the new # serversocket. pass # Similarly, stop advertising my old Zenodotus name (if any), # ignoring potential errors. try: advertisepipe.remove_from_pipe(zenodotus_advertise_handle) except: pass # Just use getmyip(), this is the default behavior and will work if we have preferences set # We only want to call getmyip() once, rather than in the loop since this potentially avoids # rebuilding the allowed IP cache for each possible port bind_ip = emulcomm.getmyip() # Attempt to have the nodemanager listen on an available port. # Once it is able to listen, create a new thread and pass it the socket. # That new thread will be responsible for handling all of the incoming connections. for portindex in range(len(configuration['ports'])): possibleport = configuration['ports'][portindex] try: # There are two possible implementations available here: # 1) Use a raw (python) socket, and so we can have a timeout, as per ticket #881 # 2) Use a repy socket, but then possibly leak many connections. # Check to see if AFFIX is enabled. try: affix_enabled_lookup = advertise_lookup( enable_affix_key)[-1] servicelogger.log("affix_enabled_lookup is " + str(affix_enabled_lookup)) # Now we check if the last entry is True or False. if affix_enabled_lookup == 'True': affix_stack_string = advertise_lookup( affix_service_key)[-1] affix_enabled = True servicelogger.log( "[INFO]: Current advertised Affix string: " + str(affix_stack_string)) else: affix_enabled = False except (AdvertiseError, TimeoutError), e: servicelogger.log( "Trying to look up Affix enabled threw " + str(type(e)) + " " + str(e)) affix_enabled = False # Raise error on debug mode. if DEBUG_MODE: raise except ValueError: servicelogger.log( "Trying to look up Affix enabled threw " + str(type(e)) + " " + str(e)) affix_enabled = False # Raise error on debug mode. if DEBUG_MODE: raise except IndexError: servicelogger.log( "Trying to look up Affix enabled threw " + str(type(e)) + " " + str(e)) # This will occur if the advertise server returns an empty list. affix_enabled = False # Raise error on debug mode. if DEBUG_MODE: raise # If AFFIX is enabled, then we use AFFIX to open up a tcpserversocket. if affix_enabled: # Here we are going to use a for loop to find a second available port # for us to use for the LegacyAffix. Since the LegacyAffix opens up two # tcpserversocket, it needs two available ports. The first for a normal # repy listenforconnection call, the second for affix enabled # listenforconnection call. # We keep track of how many times we failed to listen with the Affix # framework. If we exceed 3, we default to Repy V2 API. Note that we # will try three times with each port, if we are unable to connect # with legacy Repy V2 API as well. fail_affix_count = 0 error_list = [] for affixportindex in range( portindex + 1, len(configuration['ports'])): affixport = configuration['ports'][affixportindex] # Assign the nodemanager name to be the nodekey. We replace any whitespace in the # name and append zenodotus tag at the end. mypubkey = rsa_publickey_to_string( configuration['publickey']).replace(" ", "") myname = sha_hexhash( mypubkey) + '.zenodotus.poly.edu' myname_port = myname + ":" + str(possibleport) # Announce my (new) Zenodotus name zenodotus_advertise_handle = advertisepipe.add_to_pipe( myname, getmyip()) affix_legacy_string = "(CoordinationAffix)(LegacyAffix," + myname + "," + str( affixport) + ",0," affix_legacy_string += "(CoordinationAffix)" + affix_stack_string + ")" affix_object = AffixStackInterface( affix_legacy_string) # Now that we have found the Affix string and have created the AffixStackInterface # object, we will try to open up a listening tcp socket. If we fail to do so # 3 times, we will default to legacy Repy V2 socket. try: serversocket = affix_object.listenforconnection( myname, possibleport) servicelogger.log( "[INFO]Started accepter thread with Affix string: " + affix_legacy_string) break except (AddressBindingError, AlreadyListeningError, DuplicateTupleError), e: servicelogger.log( "Failed to open listening socket with Affix on port: " + str(affixport) + ". Found error: " + str(e)) fail_affix_count += 1 error_list.append((type(e), str(e))) # If we fail more than 2 times, we will stop attempting to try listening # on a socket with the Affix framework. if fail_affix_count > 2: servicelogger.log( "Failed to open socket using Affix after three attemps." + "Now resuming with legacy Repy socket. Errors were: " + str(error_list)) serversocket = timeout_listenforconnection( bind_ip, possibleport, 10) # assign the nodemanager name myname_port = str(bind_ip) + ":" + str( possibleport) break except Exception, e: servicelogger.log( "[ERROR] Found Listenforconnection had exception: " + str(e)) raise else: # If AFFIX is not enabled, then we open up a normal tcpserversocket. # For now, we'll use the second method. serversocket = timeout_listenforconnection( bind_ip, possibleport, 10) # assign the nodemanager name myname_port = str(bind_ip) + ":" + str(possibleport) # If there is no error, we were able to successfully start listening. # Create the thread, and start it up! accepter = nmconnectionmanager.AccepterThread(serversocket) accepter.start() # Now that we created an accepter, let's use it! set_accepter(accepter) # MOSHE: Is this thread safe!? # Now that waitforconn has been called, unset the accepter reset flag node_reset_config['reset_accepter'] = False
def start_accepter(): global accepter_thread # do this until we get the accepter started... while True: if not node_reset_config['reset_accepter'] and is_accepter_started(): # we're done, return the name! return myname_port else: # If we came here because a reset was initiated, kill the old # accepter thread server socket before starting a new one. try: accepter_thread.close_serversocket() servicelogger.log( "Closed previous accepter thread server socket.") except: # There was no accepter_thread, or it couldn't .close_serversocket(). # No problem -- this means nothing will be in the way of the new # serversocket. pass # Use getmyip() to find the IP address the nodemanager should # listen on for incoming connections. This will work correctly # if IP/interface preferences have been set. # We only want to call getmyip() once rather than in the loop # since this potentially avoids rebuilding the allowed IP # cache for each possible port bind_ip = getmyip() # Attempt to have the nodemanager listen on an available port. # Once it is able to listen, create a new thread and pass it the socket. # That new thread will be responsible for handling all of the incoming connections. for possibleport in configuration['ports']: try: # Use a Repy socket for listening. This lets us override # the listenforconnection function with a version using an # Affix stack easily; furthermore, we can transparently use # the Repy sockettimeout library to protect against malicious # clients that feed us endless data (or no data) to tie up # the connection. try: serversocket = timeout_listenforconnection( bind_ip, possibleport, 10) except (AlreadyListeningError, DuplicateTupleError), e: # These are rather dull errors that will result in us # trying a different port. Don't print a stack trace. servicelogger.log( "[ERROR]: listenforconnection for address " + bind_ip + ":" + str(possibleport) + " failed with error '" + repr(e) + "'. Retrying.") continue # Assign the nodemanager name. # We re-retrieve our address using getmyip as we may now be using # a zenodotus name instead. myname_port = str(getmyip()) + ":" + str(possibleport) # If there is no error, we were able to successfully start listening. # Create the thread, and start it up! accepter = nmconnectionmanager.AccepterThread(serversocket) accepter.start() # Now that we created an accepter, let's use it! set_accepter(accepter) # MOSHE: Is this thread safe!? # Now that waitforconn has been called, unset the accepter reset flag node_reset_config['reset_accepter'] = False except Exception, e: # print bind_ip, port, e servicelogger.log( "[ERROR] setting up nodemanager serversocket " + "on address " + bind_ip + ":" + str(possibleport) + ": " + repr(e)) servicelogger.log_last_exception() else: break
def start_accepter(): global accepter_thread # do this until we get the accepter started... while True: if not node_reset_config['reset_accepter'] and is_accepter_started(): # we're done, return the name! return myname_port else: # If we came here because a reset was initiated, kill the old # accepter thread server socket before starting a new one. try: accepter_thread.close_serversocket() servicelogger.log("Closed previous accepter thread server socket.") except: # There was no accepter_thread, or it couldn't .close_serversocket(). # No problem -- this means nothing will be in the way of the new # serversocket. pass # Just use getmyip(), this is the default behavior and will work if we have preferences set # We only want to call getmyip() once, rather than in the loop since this potentially avoids # rebuilding the allowed IP cache for each possible port bind_ip = getmyip() # Attempt to have the nodemanager listen on an available port. # Once it is able to listen, create a new thread and pass it the socket. # That new thread will be responsible for handling all of the incoming connections. for portindex in range(len(configuration['ports'])): possibleport = configuration['ports'][portindex] try: # There are two possible implementations available here: # 1) Use a raw (python) socket, and so we can have a timeout, as per ticket #881 # 2) Use a repy socket, but then possibly leak many connections. # For now, we'll use the second method and use the sockettimeout # library so we can still use a timeout to ensure we don't have # any malicious clients that feed us endless data (or no data) # to tie up the connection. Note that if we are using Affix, # we will be using a TimeoutAffix to achieve the equivalent # outcome. serversocket = timeout_listenforconnection(bind_ip, possibleport,10) # assign the nodemanager name. # We re-retrieve our address using getmyip as we may now be using # a zenodotus name instead. myname_port = str(getmyip()) + ":" + str(possibleport) # If there is no error, we were able to successfully start listening. # Create the thread, and start it up! accepter = nmconnectionmanager.AccepterThread(serversocket) accepter.start() # Now that we created an accepter, let's use it! set_accepter(accepter) # MOSHE: Is this thread safe!? # Now that waitforconn has been called, unset the accepter reset flag node_reset_config['reset_accepter'] = False except Exception, e: # print bind_ip, port, e servicelogger.log("[ERROR]: when calling listenforconnection for the connection_handler: " + str(e)) servicelogger.log_last_exception() else: break else: servicelogger.log("[ERROR]: cannot find a port for recvmess")