def _on_circuit_creation_failure(self, failure, circ): log_ex(failure, "circuit creation failed", [TorCtl.ErrorReply]) #make sure it is no longer in our collections of circuits: if circ in self.circuits: self.circuits.remove(circ) if circ in self.liveCircuits: self.liveCircuits.remove(circ)
def copy_file(fromFile, toFile): """Copy file, return success, print any errors""" try: shutil.copy(fromFile, toFile) except Exception, error: log_ex(error, "copy_file failed") return False
def success(self, data): """Called when all data has finished downloading. Validates the the length of the data is proper given any relevant headers, and calls successCB or failure appropriately @param data: the data downloaded from the HTTPDownloader (None if we were saving to a file) @type data: str or None""" if not self.requestDone: self.requestDone = True try: #validate that the file length is right if there were headers: if not self.fileName: data = self.file.getvalue() self.file.really_close() dataSize = len(data) else: dataSize = os.path.getsize(self.fileName) if self.protocolInstance.headers.has_key('content-length'): headerSize = int(self.protocolInstance.headers['content-length'][0]) if not headerSize == dataSize: raise DownloadSizeError("Downloaded size was %s. Header content-length size was %s." % (dataSize, headerSize)) except Exception, e: self.failure(e) else: try: if not self.fileName: self.successCB(data, self) else: self.successCB(self.fileName, self) except Exception, e: log_ex(e, "HTTPClient failed during success callback. url=%s" % (self.url))
def launch_failed(self, reason): log_ex(reason, "Failed to launch application: %s" % (self.name), [DependencyError]) GUIController.get().show_msgbox("Failed to launch %s: %s" % (self.name, reason), title="Error", makeSafe=True) if self.startupDeferred: tempDeferred = self.startupDeferred self.startupDeferred = None tempDeferred.callback(False)
def _on_process_done(self, result): """Used as both a callback and errback for when the _wait thread finishes or fails""" self.done = True if type(result) == type(True): return result log_ex(result, "Failure in PseudoProcess") return False
def file_exists(fileName): """@returns: a boolean of whether the file exists""" try: ret = os.path.exists(fileName) return ret except Exception, error: log_ex(error, "file_exists failed")
def error(self, failure): #ignore shutdown errors if ProgramState.DONE: return log_ex(failure, "Error while submitting logs via FTP") if self.cb: self.cb(False)
def error(failure): if not self.is_done(): if Basic.exception_is_a(failure, [TorCtl.TorCtlClosed, TorCtl.ErrorReply]): log_msg("Failed to create PAR client, closing", 1, "circuit") else: log_ex(failure, "Unexpected failure while starting circuit") self.on_done()
def validate_php_output(response): """The script should return an integer. Anything else indicates a failure.""" try: response = int(response) return True except Exception, e: log_ex(e, "PHP account creation failed: %s\n%s" % (response, args))
def get_pid_from_port(port): """Figure out the process that has launched a connection from port. Returns the pid, or 0 on failure""" port = int(port) try: #read in netstat -pant p = subprocess.Popen("netstat -pant 2>/dev/null | grep %s" % (port), shell=True, stdout=subprocess.PIPE) p.wait() data = p.stdout.read() if not data: return 0 lines = data.split("\n") #pop the last line (it's empty) lines.pop() #for each of the program/port bindings: for line in lines: line = line.split() localAddr = line[3] remoteAddr = line[4] #dont bother with remote addresses if localAddr.rfind(":::") != -1 or remoteAddr.rfind(":::") != -1: continue localAddr = localAddr.split(":") remoteAddr = remoteAddr.split(":") #if these are the droids we're looking for: if localAddr[0] in ("0.0.0.0", "127.0.0.1") and remoteAddr[0] in ("0.0.0.0", "127.0.0.1") and int(localAddr[1]) == port: process = line[6].split("/") return process[0] except Exception, e: log_ex(e, "While doing linux portmapping")
def lineReceived(self, line): """Main subthread loop: Read commands from Tor, and handle them either as events or as responses to other commands. """ try: isEvent = self.parse_line(line) except: self._err(sys.exc_info()) return if isEvent == None: return reply = self._lines try: if isEvent: if self._handler is not None: self.handle_event(time.time(), reply) else: cb = self._callbackQueue.pop(0) cb(reply) except Exception, e: errorMsg = "Tor control callback failed" if isEvent: errorMsg = "Tor event handler failed" log_ex(e, errorMsg)
def _subprocess_finished(self, result, p): if result == True: self.remove_process(p) if len(self.processes) <= 0: self._all_subprocesses_done() elif result != False: log_ex(result, "Failed while waiting for subprocess")
def get_all_processes(): processList = [] hProcessSnap = c_void_p(0) hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 ) try: pe32 = PROCESSENTRY32() pe32.dwSize = sizeof( PROCESSENTRY32 ) ret = Process32First( hProcessSnap , pointer( pe32 ) ) while ret : hProcess = OpenProcess( PROCESS_ALL_ACCESS , 0 , pe32.th32ProcessID ) try: dwPriorityClass = GetPriorityClass( hProcess ) if dwPriorityClass != 0 : hModuleSnap = c_void_p(0) me32 = MODULEENTRY32() me32.dwSize = sizeof( MODULEENTRY32 ) exePath = "" hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pe32.th32ProcessID ) try: ret = Module32First( hModuleSnap, pointer(me32) ) if ret != 0 : exePath = me32.szExePath finally: CloseHandle( hModuleSnap ) processList.append((pe32.th32ProcessID, exePath, pe32.th32ParentProcessID)) finally: CloseHandle( hProcess ) ret = Process32Next( hProcessSnap, pointer(pe32) ) except Exception, e: log_ex(e, "Error while getting detailed process list")
def _on_response(self, dialog, responseId): """Let the base class handle the response. Then destroy the dialog unless the base class says not to.""" #let the base class handle the response: try: result = self.on_response(responseId) except Exception, error: log_ex(error, "Failure while handling response for '%s' dialog" % (self.title)) return
def errReceived(self, data): """receives output from stderr""" self.transport.loseConnection() if self.errback: self.deferred.errback(data) else: log_ex('No errback attached to process to handle stderr%s' % (data), 0)
def delete_file(fileName, silent=False): """Delete a file with the option of failing silently. Be careful.""" try: os.remove(fileName) except Exception, error: if not silent: log_ex(error, "delete_file failed") return False
def start(self): """Open the forwarded port.""" self.reachableState = "UNKNOWN" self.upnpState = "UNKNOWN" try: self.start_upnp() except Exception, e: log_ex(e, "Failure while checking that port %s is properly forwarded" % (self.name))
def on_new_relay(self, r): try: assert isinstance(r.desc.nickname, basestring), "nickname must be a string" assert type(r.desc.idhex) == types.StringType, "idhex must be a string" for i in range(0,3): self.routerCombos[i].append_text(r.desc.nickname + "~" + r.desc.idhex) except Exception, e: log_ex(e, "Problem while updating routers in circuitlist")
def error(failure): # this happens occasionally when the circuit is closed at approximately the same time that we send a payment # it can be safely ignored because the circuit is closed and we already learned about it if "552 Cannot find circuit with id" in str(failure): log_msg("A circuit that we tried to send a payment message to was closed. Oops.", 4) self.close() return # otherwise, log an error because this is unexpected log_ex(failure, "SENDPAYMENT failed for circuit=%s" % (nextCircId), [TorCtl.ErrorReply])
def err(self, err, optional=None): """returns an error msg""" log_ex(err, "Unhandled error from %s" % (self.transport.getPeer())) #DEBUG: NOTE: this is a security vulnerability otherwise if optional: rep = "%s\nerr: %s"%(optional, err) else: rep = "Error with login!" self.reply(rep)
def closed_event(self, tp, ex, tb): """Called when Tor control connection is closed""" ignoreList = [ConnectionDone] if self.torApp.is_stopping() or not self.torApp.is_running(): ignoreList += [ConnectionLost] log_ex(ex, "Tor failure", ignoreList, reasonTraceback=tb, excType=tp) if self.torApp.isReady: log_msg("Tor Control port was closed! reason: %s" % (ex), 0) self.torApp.on_done()
def on_apply(self, app, category): try: self.set_start_on_boot(self.startBitBlinderOnBoot) self.set_half_open_conns(app, self.halfOpenConnections) # #TEMP: re-enable this # self.apply_anon_mode() except Exception, e: log_ex(e, "Failed to apply settings:") return False
def close(self): for file, f in self.handles.items(): try: self.unlock_file(file, f) except Exception, e: log_ex(e, "Failed to unlock") try: f.close() except Exception, e: log_ex(e, "Failed to close")
def init_priority(self, new_priority): try: assert len(new_priority) == self.numfiles for v in new_priority: assert type(v) in (type(0), type(0L)) assert v >= -1 assert v <= 2 except Exception, e: log_ex(e, "Error when setting priority") return False
def exit(self): shutdownDeferred = defer.Deferred() try: #for every process that did not yet exit, kill it for processObj in self.processes: #TODO: change to this once kill_recursive runs on linux: #kill_recursive(p.pid) System.kill_process(processObj.pid) except Exception, error: log_ex(error, "Failed to kill Application process:")
def _port_test_failure(reason): # is this one of the errors that corresponds to unreachability? if Basic.exception_is_a(reason, [CannotListenError, TimeoutError]): return False # otherwise, we do not know the state of reachability (None signals that) # and log the error if necessary unexpectedException = not Basic.exception_is_a(reason, [ConnectError]) if unexpectedException: log_ex(reason, "Unexpected failure while testing port") return None
def start_upnp(self): """Start the attempt to forward the port. This function is idempotent.""" if not self.startedUPNP: self.startedUPNP = True #try to set the new ports for Tor: try: #try forwarding the new port from the router: self._upnp_request() except Exception, error: log_ex(error, "Failed to start UPNP")
def _listener(self): """listens for keystrokes from the user and puts them in the Queue""" self.stdscr.timeout(500) while self.shouldListen: k = self.stdscr.getch() if k == -1: continue try: self.q.put(k) except Exception, e: log_ex(e, 'Couldn\'t shove in queue')
def _trigger_event(self, eventName, *args, **kwargs): """deal with an event--call all handlers""" assert eventName in self._knownEventNames, "Tried to trigger an unknown event (%s)" % (eventName) if eventName not in self._eventListenerMapping: return handlers = self._eventListenerMapping[eventName] for handler in handlers: try: handler(self, *args, **kwargs) except Exception, error: log_ex(error, "Failure while handling event %s on %s" % (eventName, self))
def throw_event(eventName, *args, **kwargs): """Custom event handling. Inform all interested listeners about the event. @param eventName: the event that just occurred @type eventName: str""" if GLOBAL_EVENT_LISTENERS.has_key(eventName): for x in GLOBAL_EVENT_LISTENERS[eventName]: try: func = getattr(x, "on_" + eventName) if func: func(*args, **kwargs) except Exception, e: log_ex(e, "%s failed while handling %s event" % (x, eventName))
def handle_twisted_err(_stuff=None, _why=None, quitFunc=quitFunc, **kw): excType = None tb = None #get the exception from the system if necessary if not _stuff or issubclass(type(_stuff), Exception): (excType, _stuff, tb) = sys.exc_info() #check if this is a shutdown signal if quitFunc and _stuff and issubclass(type(_stuff), KeyboardInterrupt): log_msg("Shutting down from keyboard interrupt...", 0) quitFunc() return #otherwise, log the exception if excType and tb: log_ex(_stuff, "Unhandled exception from Twisted:", reasonTraceback=tb, excType=excType) else: log_ex(_stuff, "Unhandled failure from Twisted:")
def read_routers(self, nslist): """ Given a list a NetworkStatuses in 'nslist', this function will return a list of new Router instances. """ bad_key = 0 new = [] for ns in nslist: try: r = self.get_router(ns) new.append(r) except ErrorReply: bad_key += 1 if "Running" in ns.flags: plog( "NOTICE", "Running router " + ns.nickname + "=" + ns.idhex + " has no descriptor") except Exception, e: log_ex(e, "Unexpected error while loading routers") continue
def update_coins(self): """Check that we have enough ACoins locally, but not too many, and none that are about to expire""" try: self.check_wallet_balance() #should we consider sending a deposit message? if not self.acoinDepositInProgress: coins = [] curTime = time.time() #we must retry depositing any existing coins that are in progress: if len(self.depositingACoins) > 0: coins += self.depositingACoins #are any stale? if curTime > self.beginDepositACoinTime: if self.ACoins.has_key( self.currentACoinInterval - 1) and len( self.ACoins[self.currentACoinInterval - 1]): newCoins = [] for coin in self.ACoins[self.currentACoinInterval - 1]: newCoins.append(coin) if len(newCoins) >= ACOIN_BATCH_SIZE: break for coin in newCoins: self.remove_coin(coin) coins += list(newCoins) if len(coins) > 0: #make sure we have enough coins: self.check_wallet_balance() #do we have too many? numCoins = (self.get_wallet_balance() - ACOIN_HIGH_LEVEL) if numCoins > 0: coins += self.get_acoins(ACOIN_BATCH_SIZE, False) #if we have coins to deposit, or we need to learn about the next interval if coins or curTime > self.curIntervalExpiration + self.intervalLearningDelay: self.acoinDepositInProgress = True self.deposit_acoins(coins) except Exception, e: log_ex( e, "Too many ACoins, but failed when trying to send to the bank")
def on_new_stream(self, event): #will automatically register itself with it's application stream = Stream.Stream(event) #figure out who should handle the stream next: if stream.isInternal and Stream.OBSERVE_INTERNAL: stream.app = self.torApp stream.app.on_new_stream(stream) else: try: #first check if this was launched internally, directly through Tor: #TODO: this is a little weird, multiple failure conditions: if self.waiting_for_stream(stream): self.handle_stream_creation(stream) return port = int(event.source_addr.split(":")[1]) #need to figure out the original application that started this: assert port, "port must be defined to map a Stream to an Application" pid = System.get_pid_from_port(port) assert pid != 0, "pid must be non-zero in order to map from a Stream to Application" originalApp = self.get_app_by_pid(pid) originalApp.on_new_stream(stream, None) except Exception, e: log_ex(e, "No app for stream=%d?" % (stream.id))
def _start_connection_from_queue(self): try: if not self.paused: numOpened = 0 #connect to peers that we have never connected to before while len(self.never_connected) > 0: if self._should_connect_to_new_peer(numOpened): peer = self.never_connected.pop(0) dns, id, encrypted = peer self.start_connection(dns, id, encrypted) self.prev_connected.append(peer) numOpened += 1 else: break #connect to peers that have had succesful connections previously while len(self.to_connect) > 0: if self._should_connect_to_new_peer(numOpened): dns, id, encrypted = self.to_connect.pop(0) self.start_connection(dns, id, encrypted) numOpened += 1 else: break #reduce the prev_connected array to 300 in the event it gets larger if len(self.prev_connected) >= 300: del self.prev_connected[:len(self.prev_connected) - 300] #TODO: kinda stupid that we just keep cycling through the last list of peers, but we need some list of them so that we can retry when circuits go down #Better ideas include a global cache of peers obtained from PX, DHT, etc, or even a cache incorporating time last seen for peers from trackers if len(self.to_connect) <= 0: #dont repeatedly try the same peers more than once every RETRY_INTERVAL curTime = time.time() if curTime > self.lastPeerCycleTime + self.PEER_RETRY_INTERVAL: self.lastPeerCycleTime = curTime log_msg("Cycling through the list of peers again...", 2, "btconn") self.to_connect = copy.copy(self.prev_connected) except Exception, e: log_ex(e, "Failed while starting BT connections")
def test_network_state(): try: #test network basics--are we firewalled, is dns working, are the test servers reachable? testServerDeferred = test_test_servers() test_dns() #then do the tests that require the test servers: #test outgoing ports d = test_outgoing_port(80) def is_port_80_reachable(isReachable): global _isPort80Reachable _isPort80Reachable = isReachable return isReachable d.addCallback(is_port_80_reachable) d = test_outgoing_port(443) def is_port_443_reachable(isReachable): global _isPort443Reachable _isPort443Reachable = isReachable return isReachable d.addCallback(is_port_443_reachable) test_random_outgoing_port() #test incoming connections test_udp() #what kind of speeds have we seen over this network? upload vs download? #what interface should we be binding? except Exception, e: log_ex(e, "Error while testing network state")
def failure(self, failure): """Called when a download fails for any reason @param failure: the reason that the download failed @type failure: Exception, Failure, or str""" if not self.requestDone: try: self.requestDone = True #ensure that the network connection is closed (so it doesnt keep writing to our buffer) if self.protocolInstance and self.protocolInstance.transport: self.protocolInstance.transport.loseConnection() #and close our buffer: if not self.fileName: self.file.really_close() #call the registered failure handler if self.failureCB: self.failureCB(failure, self) #and if there is not one, log the error by default else: log_ex(failure, "HTTPClient failed. url=%s" % (self.url)) except Exception, e: log_ex( e, "HTTPClient failed during failure callback. url=%s" % (self.url)) finally:
def _remove_upnp(self): """Actually call the outside program to remove the UPNP binding. Returns a deferred that will be triggered when the port binding has finished (either successfully or unsuccessfully)""" #failures just get printed out, because we cant really do anything about them def handle_failure(failure): log_msg( "Failed to remove UPNP mapping on shutdown: %s" % (failure), 1) try: #figure out our local IP address localIP = Twisted.get_lan_ip() #launch the program output = self._start_upnp_exe( ("-m", localIP, "-d", str(self.port), self.trafficType)) #handle results output.addCallback(self._upnp_removed) output.addErrback(handle_failure) return output except Exception, error: log_ex(error, "Failed send request to remove UPNP") handle_failure("Never even sent the request :(")
def handle_exception(excType, value, tb): log_ex(value, "Unhandled exception in main loop:", reasonTraceback=tb, excType=excType)
def request_failed(self, error, httpDownloadInstance=None): self.downloadingUpdate = False log_ex(error, "Error while downloading update", [DownloadSizeError]) #lets try the full installer instead then Scheduler.schedule_once(30 * 60, self.check_for_updates)
def error_handler(failure): """Log an error if the script did not finish cleanly.""" log_ex(failure, "PHP script had an error:")
def failure(reason): log_ex(reason, "Failed while checking Tor bootstrap progress", [TorCtl.TorCtlClosed])
def failure(error): log_ex( error, "Stream (%s) failed to attach to Circuit (%s)" % (stream.id, self.id), [TorCtl.ErrorReply]) stream.ignoreCircuits.add(self)
def failure_cb(reason): log_ex(reason, "External connection failed to connect to SOCKS proxy")
def generic_error_handler(self, error): log_ex(error, "Something bad happened", [InsufficientACoins])
def error(failure): log_ex(failure, "Failed to add tokens for circuit=%s" % (circId), [TorCtl.ErrorReply])
def failure(error): if self.app.is_ready() or self.app.is_starting(): log_ex(error, "Stream (%d) failed to close" % (self.id), [TorCtl.ErrorReply])
def hash_failed(self, error): self.downloadingUpdate = False log_ex(error, "Error while verifying update") #lets just try again in half an hour or something Scheduler.schedule_once(30 * 60, self.check_for_updates)
def update(): if ProgramState.DO_UPDATES: try: obj.on_update() except Exception, error: log_ex(error, "During update for %s" % (obj))
def _startup_failure(self, reason): self.startupDeferred = None log_ex(reason, "BitBlinder failed to start up!") return reason
def error(failure): log_ex(failure, "Circuit (%d) failed to close" % (self.id), [TorCtl.ErrorReply])
def uac_done(result): self.startOnBootDeferred = None if result != True: log_ex( result, "Bad result while running BitBlinderSettingsUpdate.exe")
def _handle_error(self, reason): """Log the error, and reply with UKNOWN_ERROR. Note that this is obviously only for unexpected errors. Other errors should have their own error codes.""" log_ex(reason, "Unhandled error during account creation") self._reply(RESPONSE_CODES["UNKNOWN_ERROR"])
def read_args(): #Create the options parser, this will be used throughout the program's execution Globals.PARSER = optparse.OptionParser() #Some options that are initially important: Globals.PARSER.add_option("--WAIT_FOR_PROCESS", type="int", dest="WAIT_FOR_PROCESS", help="Dont use this", metavar="FILE") Globals.PARSER.add_option("--FINISHED_UPDATE", action="store_true", dest="FINISHED_UPDATE", default=False) Globals.PARSER.add_option("--use-existing-tor", action="store_true", dest="USE_EXISTING_TOR", default=False) Globals.PARSER.add_option("-m", "--minimize", action="store_true", dest="minimize", default=False) Globals.PARSER.add_option("--curses", action="store_true", dest="useCurses", default=False) Globals.PARSER.add_option("--no-gui", action="store_true", dest="no_gui", default=False) Globals.PARSER.add_option("--allow-multiple", action="store_true", dest="allow_multiple", default=False) Globals.PARSER.add_option("--dev-network", action="store_true", dest="dev_network", default=False) Globals.PARSER.add_option("--debug", action="store_true", dest="debug", default=False) #BitTorrent: Globals.PARSER.add_option("-t", "--torrent", dest="torrent", help="Download a torrent file", metavar="FILE") #for telling us which program to launch: Globals.PARSER.add_option("--launch-bt", action="store_true", dest="launch_bt", default=False) Globals.PARSER.add_option("--launch-bb", action="store_true", dest="launch_bb", default=False) Globals.PARSER.add_option("--launch-ff", action="store_true", dest="launch_ff", default=False) #actually parse the options: (options, args) = Globals.PARSER.parse_args() #make sure that SOMETHING is supposed to start up: if not options.launch_bb and not options.launch_bt and not options.launch_ff: sys.argv.append('--launch-bb') options.launch_bb = True #NOTE: weirdness: the WAIT_FOR_PROCESS option is ONLY here for convenience. #It takes a process id as an argument. All it does is wait for the process #with that pid and then exit. This is called by the updater batch file, #because we need to wait for the previous InnomiNet instance to exit before #updating. Because we use py2exe, I didnt want to make a separate script for that if options.WAIT_FOR_PROCESS: try: pid = options.WAIT_FOR_PROCESS log_msg( "Waiting on previous program (%s) to finish shutting down..." % (pid), 2) System.wait_for_pid(pid) log_msg("Finished waiting", 2) except Exception, error: log_ex(error, "WAIT_FOR_PROCESS failed") finally:
def cleanup_previous_update(options): #This option is defined to indicate that we just ran the updater script. We set #the appropriate global, and just try to delete the update exe ignoreUpdater = False if os.path.exists(Globals.UPDATE_FILE_NAME): #kill any leftover updater processes try: startTime = time.time() while True: updaterProcs = System.get_process_ids_by_exe_path( re.compile( "^%s$" % (Globals.UPDATE_FILE_NAME.replace("\\", "\\\\")), re.IGNORECASE)) if len(updaterProcs) <= 0: break for pid in updaterProcs: log_msg("Waiting for updater (%s) to shut down..." % (pid), 1) System.kill_process(pid) if time.time() > startTime + 10.0: raise Exception( "Waited 15 seconds and updater still had not shut down" ) else: time.sleep(1.0) except Exception, error: log_ex(error, "Failed while waiting for updater to finish") message = "The BitBlinderUpdate.exe is still running. You must wait for it to finish or forcefully close it before you can run BitBlinder again. Maybe try running BitBlinder as Administrator just once?" die(message, "Error", EXIT_CODES.BITBLINDER_ALREADY_RUNNING) #if this is the first run after an update: if options.FINISHED_UPDATE: #ok, NOW try moving the updater file startTime = time.time() while True: try: if os.path.exists(Globals.UPDATE_FILE_NAME): shutil.move(Globals.UPDATE_FILE_NAME, Globals.UPDATE_FILE_NAME + ".prev") break except Exception, error: time.sleep(0.5) if time.time() > startTime + 5.0: log_ex( error, "Failed to remove update .exe from the previous update" ) ignoreUpdater = True #ok, lets try making a file, just so I can see why this is failing for people: if issubclass(type(error), WindowsError): try: testFile = open( Globals.UPDATE_FILE_NAME + ".test", "wb") testFile.write("hello?") testFile.close() except Exception, error: log_ex(error, "And we could NOT write a file") else: log_msg( "But we successfully wrote to a file (%s) Weird." % (Globals.UPDATE_FILE_NAME + ".test")) break
def handle_payment(self, msg): """Unpack, process, and respond to a payment message. @param msg: the payment message from the origin. @type msg: str""" #if there are any failures, log them, and close the circuit: try: #read the PAR protocol version: version, msg = Basic.read_byte(msg) assert version == 1, "currently only accept PAR version 1" readTokens, msg = Basic.read_int(msg) writeTokens, msg = Basic.read_int(msg) #read their request ID too theirId, msg = Basic.read_long(msg) #read the number of coins: numCoins, msg = Basic.read_byte(msg) #read each coin: creditsEarned = 0 requests = [] for i in range(0, numCoins): #what type of coin is this? coinType, msg = Basic.read_byte(msg) #we only accept acoins for now: assert coinType == PaymentStream.COIN_TYPES[ 'A'], "bad coin type" #get the matching request: requestId, msg = Basic.read_long(msg) requests.append(requestId) assert len(msg) % numCoins == 0, "bad payment message length" coinLen = len(msg) / numCoins for requestId in requests: #if this is not true, there wont even be another part to the response assert Basic.read_byte(msg)[0] == ord( '0'), "bad leading byte in payment message" blob, msg = msg[:coinLen], msg[coinLen:] request = self.requests[requestId] del self.requests[requestId] code, sig = Basic.read_byte(blob) #validate the ACoin coin = BankMessages.parse_acoin_response( self.bank, sig, request) if not coin: raise Exception("Invalid ACoin sent for payment!") #success! creditsEarned += coin.get_expected_value() coin.originCircuit = self self.bank.on_earned_coin(coin) receiptMessageDeferred = self.send_receipt_message( theirId, numCoins) if not receiptMessageDeferred: return #check that they paid enough: requestedTokens = readTokens + writeTokens paidTokens = creditsEarned * Globals.CELLS_PER_PAYMENT if paidTokens < requestedTokens: raise Exception("Relays asked for %s, but only paid for %s" % (requestedTokens, paidTokens)) #inform Tor that we got a payment message: addTokensDeferred = self.add_tokens(readTokens, writeTokens) if not addTokensDeferred: return def response(result): if result: read, write = result log_msg( "%s paid us %s for exit stream, now %d / %d" % (Basic.clean(self.baseCircuit.prevHexId[:4]), creditsEarned, read, write), 3, "par") addTokensDeferred.addCallback(response) except Exception, error: log_ex(error, "Got bad PAR message") self.close()
self.btApp.force_stop() System.SHUTDOWN = True shutdownDeferred = BitBlinder.stop() shutdownDeferred.addCallback(self._shutdown) shutdownDeferred.addErrback(self._shutdown) def _shutdown(self, result): """Stop the main loop and cause the program to exit. This should ONLY be called after all Applications are shut down cleanly.""" Basic.validate_result(result, "MainLoop::_shutdown") #close the server that listens for new versions of the app to start up: StartupServer.stop() #remove scheduled events: if self.updateEvent and self.updateEvent.active(): self.updateEvent.cancel() ProgramState.DO_UPDATES = False self.updateEvent = None GlobalEvents.throw_event("shutdown") log_msg("Done with shutdown deferreds", 4) #close the main loop if ProgramState.USE_GTK: try: gtk.main_quit() except Exception, error: log_ex(error, "Couldn't kill the gtk main loop") else: try: Globals.reactor.stop() except Exception, error: log_ex(error, "Couldn't stop the reactor")
def on_upnp_done(self): try: self.start_test() except Exception, e: log_ex(e, "Error while starting test for port %s" % (self.name))
def stop_failure(self, reason): log_ex(reason, "%s failed to stop cleanly" % (self.name)) self.stop_done()
def on_failure(failure, instance, failure_cb=failure_cb): log_ex(failure, "Failed while downloading current version document", [ConnectionDone]) if failure_cb: failure_cb(failure, instance)