def _onAccept(self, err, sock): if err < 0: self._setError('Error accepting connection from %s.' % env.displayName) return self.rpcConn = RPCConnection(sock, self.reactor) self.fileClient = FileClient(self.rpcConn) self._setStatus('Fetching file list from %s...' % env.displayName) self.fileClient.callList('/', self._onList)
def onTCPConnect( connector ) : self.connectOp = None if connector.getError() != 0 : self.state = self.CLOSED connectCallback( False ) return self.rpcConn = RPCConnection( connector.getSock(), self.reactor ) self.rpcConn.setCloseCallback( self._onClose ) self.state = self.CONNECTED connectCallback( True )
def __init__( self, sock, reactor, routerState ) : self.rpcConn = RPCConnection( sock, reactor ) self.reactor = reactor self.routerState = routerState self.rpcConn.setCloseCallback( self.close ) self.rpcConn.setRequestCallback( self._onRequest ) self.requestTable = {} for msg in 'Ping Register Connect Accept'.split() : self.requestTable[msg] = getattr( self, '_do%s' % msg ) self.routerState.handlers[self] = 1 self.state = self.INITIAL self._lastActiveTime = time()
def _doOfferFiles(self, sock): self._setStatus('Sending request ...') self.state = self.OFFERINGFILES fileList = [] for row in range(self.ui.fileList.count()): item = self.ui.fileList.item(row) fileList.append(self.fileItems[item][0]) self.rpcConn = RPCConnection(sock, self.reactor) self.switchboard = RPCSwitchboard(self.rpcConn) self.fs = FlatFS(fileList) self.fileServer = FileServer(self.fs, self.switchboard) pending = {} for i, f in enumerate(fileList): pending[os.path.split(f)[1].lower()] = i def onClose(): if pending: self._setError('Disconnected.') else: self._setStatus('Completed.') def onTransferStatus(payload): if type(payload) is not ListType: return if len(payload) != 4: return for x in payload: if type(x) is not IntType: return if x < 0: return fileId, numFiles, transferred, fileSize = payload if numFiles != len(fileList): return if not (1 <= fileId <= numFiles): return if transferred > fileSize: return fname = os.path.split(fileList[fileId - 1])[1] lfname = fname.lower() pos = pending.get(lfname, None) if pos is None: return if transferred == fileSize: percent = 100 del pending[lfname] else: percent = transferred * 100 / fileSize self._setStatus('Sending file (%d/%d): %s (%d%%)' % (pos + 1, len(fileList), fname, percent)) self.switchboard.addOnewayAgent('TransferStatus', onTransferStatus) self.rpcConn.setCloseCallback(onClose)
def onTCPConnect( connector ) : obj.op = None if connector.getError() != 0 : onError() return obj.rpcConn = RPCConnection( connector.getSock(), reactor ) obj.rpcConn.setCloseCallback( onError ) obj.op = _doRPCCall( obj.rpcConn, 'Connect', [routerId], onRouterConnect )
def _onAccept( self, err, sock ) : if err < 0 : self._setError( 'Error accepting connection from %s.' % env.displayName ) return self.rpcConn = RPCConnection( sock, self.reactor ) self.fileClient = FileClient( self.rpcConn ) self._setStatus( 'Fetching file list from %s...' % env.displayName ) self.fileClient.callList( '/', self._onList )
def _doOfferFiles( self, sock ) : self._setStatus( 'Sending request ...' ) self.state = self.OFFERINGFILES fileList = [] for row in range(self.ui.fileList.count()) : item = self.ui.fileList.item( row ) fileList.append( self.fileItems[item][0] ) self.rpcConn = RPCConnection( sock, self.reactor ) self.switchboard = RPCSwitchboard( self.rpcConn ) self.fs = FlatFS( fileList ) self.fileServer = FileServer( self.fs, self.switchboard ) pending = {} for i,f in enumerate(fileList) : pending[os.path.split(f)[1].lower()] = i def onClose() : if pending : self._setError( 'Disconnected.' ) else : self._setStatus( 'Completed.' ) def onTransferStatus( payload ) : if type(payload) is not ListType : return if len(payload) != 4 : return for x in payload : if type(x) is not IntType : return if x < 0 : return fileId,numFiles,transferred,fileSize = payload if numFiles != len(fileList) : return if not (1 <= fileId <= numFiles) : return if transferred > fileSize : return fname = os.path.split(fileList[fileId-1])[1] lfname = fname.lower() pos = pending.get( lfname, None ) if pos is None : return if transferred == fileSize : percent = 100 del pending[lfname] else : percent = transferred*100 / fileSize self._setStatus( 'Sending file (%d/%d): %s (%d%%)' % (pos+1,len(fileList),fname,percent) ) self.switchboard.addOnewayAgent( 'TransferStatus', onTransferStatus ) self.rpcConn.setCloseCallback( onClose )
class FileReceiverWindow(QWidget, FlashWindow): def __init__(self, reactor): QWidget.__init__(self) FlashWindow.__init__(self, reactor) self.ui = Ui_FileReceiverWindow() self.ui.setupUi(self) self.reactor = reactor self.setWindowTitle(env.displayName + ' - ' + str(self.windowTitle())) self.connect(self.ui.acceptButton, SIGNAL('clicked()'), self._onAcceptFiles) self.connect(self.ui.cancelButton, SIGNAL('clicked()'), self.close) tcpConnect(('127.0.0.1', env.port), self.reactor, self._onConnect) self._setStatus('Connecting to CSpace...') self.disconnected = False def _setStatus(self, text, isError=False): lines = text.split('\n') text = '<b>%s</b>' % '<br/>'.join(lines) if isError: text = '<font color=red>%s</font>' % text self.ui.status.setText(text) def _setError(self, text): self._setStatus(text, True) self.ui.cancelButton.setText('&Close') def _onConnect(self, connector): if connector.getError() != 0: self._setError('Error connecting to CSpace.') return sock = connector.getSock() self._setStatus('Accepting connection from %s.' % env.displayName) CSpaceAcceptor(sock, env.connectionId, self.reactor, self._onAccept) def _onAccept(self, err, sock): if err < 0: self._setError('Error accepting connection from %s.' % env.displayName) return self.rpcConn = RPCConnection(sock, self.reactor) self.fileClient = FileClient(self.rpcConn) self._setStatus('Fetching file list from %s...' % env.displayName) self.fileClient.callList('/', self._onList) def _onList(self, err, result): if err != 0: self._setError('Error fetching file list from %s.' % env.displayName) return self.files = [] for x in result: if not x.endswith('/'): self.files.append(x) self.ui.fileList.addItem(x) self._setStatus(('%s is sending the following files.\n' % env.displayName) + 'Would you like to accept?') self.ui.acceptButton.setEnabled(True) self.rpcConn.setCloseCallback(self._onClose) self.flash() def _onClose(self): self.disconnected = True self._setError('Disconnected.') self.ui.acceptButton.setEnabled(False) def _chooseTargetDir(self): defaultDir = os.path.expanduser('~/Desktop') if not os.path.isdir(defaultDir): defaultDir = QString() dir = localSettings().getString('Settings/FileReceiverSaveDir') if (not dir) or (not os.path.isdir(dir)): dir = defaultDir while True: dir = QFileDialog.getExistingDirectory( self, 'Choose directory to save the file(s)', dir) if dir.isEmpty(): return None dir = str(dir) existing = [] for f in self.files: if os.path.exists(os.path.join(dir, f)): existing.append(f) if not existing: break msg = 'The following file(s) already exist in\n%s.\nWould you like to overwrite?\n%s' % ( dir, '\n'.join(existing)) result = QMessageBox.question( self, 'Overwrite Prompt', msg, QMessageBox.Yes, QMessageBox.No, QMessageBox.Cancel | QMessageBox.Escape) if result == QMessageBox.Yes: break if result == QMessageBox.No: continue assert result == QMessageBox.Cancel return None localSettings().setString('Settings/FileReceiverSaveDir', dir) return dir def _onAcceptFiles(self): self.ui.acceptButton.setEnabled(False) targetDir = self._chooseTargetDir() if self.disconnected: return if not targetDir: self.ui.acceptButton.setEnabled(True) return self.targetDir = targetDir self.curFileId = 0 self.rpcConn.setCloseCallback(None) self.statusStub = RPCStub(self.rpcConn, 'TransferStatus') self._doTransfer() def _doTransfer(self): if self.curFileId >= len(self.files): self._setStatus('Completed.') self.ui.cancelButton.setText('&Close') self.rpcConn.close(deferred=True) return fname = self.files[self.curFileId] self.curFileId += 1 self._setStatus('Receiving file(%d/%d): %s' % (self.curFileId, len(self.files), fname)) remotePath = '/' + fname localPath = os.path.join(self.targetDir, fname) try: self.fetcher = FileFetcher(self.fileClient, remotePath, localPath, self._onTransfer) except (OSError, IOError), e: self._setError('Error saving file: %s' % localPath) return
class RouterServerHandler( object ) : (INITIAL,REGISTERED,CONNECTING,CLOSED) = range(4) def __init__( self, sock, reactor, routerState ) : self.rpcConn = RPCConnection( sock, reactor ) self.reactor = reactor self.routerState = routerState self.rpcConn.setCloseCallback( self.close ) self.rpcConn.setRequestCallback( self._onRequest ) self.requestTable = {} for msg in 'Ping Register Connect Accept'.split() : self.requestTable[msg] = getattr( self, '_do%s' % msg ) self.routerState.handlers[self] = 1 self.state = self.INITIAL self._lastActiveTime = time() def close( self ) : self.rpcConn.close() del self.routerState.handlers[self] if self.state == self.REGISTERED : del self.routerState.registered[self.routerId] elif self.state == self.CONNECTING : del self.routerState.connecting[self.connectionId] self.state = self.CLOSED def lastActiveTime( self ) : return self._lastActiveTime def sendIncoming( self, connectionId ) : assert self.state == self.REGISTERED self.rpcConn.oneway( connectionId ) def _onRequest( self, payload, ctx ) : self._lastActiveTime = time() try : assert type(payload) is list assert len(payload) >= 1 msg = payload.pop( 0 ) assert type(msg) is str handler = self.requestTable.get( msg ) assert handler is not None except : ctx.response( [-1] ) return handler( payload, ctx ) def _doPing( self, args, ctx ) : try : peerAddr = self.rpcConn.getSock().getpeername() except sock_error : ctx.response( [-1] ) return ctx.response( (0,peerAddr) ) def _doRegister( self, args, ctx ) : try : assert self.state == self.INITIAL assert len(args) == 0 except : ctx.response( (-1,'') ) return while True : routerId = rand_bytes( 20 ) if routerId not in self.routerState.registered : break self.routerId = routerId self.state = self.REGISTERED self.routerState.registered[routerId] = self ctx.response( (0,self.routerId) ) def _doConnect( self, args, ctx ) : try : assert self.state == self.INITIAL assert len(args) == 1 routerId = args[0] assert type(routerId) is str handler = self.routerState.registered.get( routerId ) assert handler is not None except : ctx.response( [-1] ) return while True : connectionId = rand_bytes( 20 ) if connectionId not in self.routerState.connecting : break self.connectionId = connectionId self.connectCtx = ctx self.state = self.CONNECTING self.routerState.connecting[connectionId] = self handler.sendIncoming( connectionId ) def finishConnect( self ) : assert self.state == self.CONNECTING self.connectCtx.response( [0] ) del self.routerState.connecting[self.connectionId] del self.routerState.handlers[self] sock = self.rpcConn.getSock() pendingWrite = self.rpcConn.getPendingWrite() self.rpcConn.shutdown() self.state = self.CLOSED return (sock,pendingWrite) def _doAccept( self, args, ctx ) : try : assert self.state == self.INITIAL assert len(args) == 1 connectionId = args[0] assert type(connectionId) is str handler = self.routerState.connecting.get( connectionId ) assert handler is not None except : ctx.response( [-1] ) return sock1,pendingWrite1 = handler.finishConnect() ctx.response( [0] ) del self.routerState.handlers[self] sock2 = self.rpcConn.getSock() pendingWrite2 = self.rpcConn.getPendingWrite() self.rpcConn.shutdown() self.state = self.CLOSED BridgeInitiator( sock1, pendingWrite1, sock2, pendingWrite2, self.reactor, self.routerState )
class FileSenderWindow( QWidget ) : SELECTINGFILES = 0 CONNECTINGCSPACE = 1 CONNECTINGUSER = 2 OFFERINGFILES = 3 def __init__( self, reactor ) : QWidget.__init__( self ) self.ui = Ui_FileSenderWindow() self.ui.setupUi( self ) self.reactor = reactor self._setStatus( 'Drag and drop files to be sent...' ) self.setWindowTitle( env.contactName + ' - ' + str(self.windowTitle()) ) self.setAcceptDrops( True ) self.files = {} self.fileItems = {} self.connect( self.ui.fileList, SIGNAL('itemSelectionChanged()'), self._onFileSelectionChanged ) self.connect( self.ui.addFilesButton, SIGNAL('clicked()'), self._onAddClicked ) self.connect( self.ui.removeFilesButton, SIGNAL('clicked()'), self._onRemoveClicked ) self.connect( self.ui.removeAllButton, SIGNAL('clicked()'), self._onRemoveAllClicked ) self.connect( self.ui.sendFilesButton, SIGNAL('clicked()'), self._onSendFilesClicked ) self.connect( self.ui.closeButton, SIGNAL('clicked()'), self.close ) self.state = self.SELECTINGFILES def _setStatus( self, text, isError=False ) : lines = text.split( '\n' ) text = '<b>%s</b>' % '<br>'.join(lines) if isError : text = '<font color=red>%s</font>' % text self.ui.status.setText( text ) def _setError( self, text ) : self._setStatus( text, True ) def _removeFile( self, item ) : info = self.fileItems.pop( item ) self.ui.fileList.takeItem( self.ui.fileList.row(item) ) fname = os.path.split( info[0] )[1] del self.files[fname.lower()] if not self.files : self.ui.sendFilesButton.setEnabled( False ) self.ui.removeAllButton.setEnabled( False ) def _addFile( self, f ) : if not os.path.isfile(f) : return False fname = os.path.split(f)[1] k = fname.lower() info = self.files.get( k, None ) if info is not None : self._removeFile( info[1] ) item = QListWidgetItem( fname, self.ui.fileList ) info = [f,item] self.files[k] = info self.fileItems[item] = info self.ui.sendFilesButton.setEnabled( True ) self.ui.removeAllButton.setEnabled( True ) def _onFileSelectionChanged( self ) : if self.state != self.SELECTINGFILES : return selectCount = 0 for item in self.fileItems.keys() : if self.ui.fileList.isItemSelected(item) : selectCount += 1 self.ui.removeFilesButton.setEnabled( selectCount > 0 ) def dragEnterEvent( self, ev ) : if self.state != self.SELECTINGFILES : return mimeData = ev.mimeData() if mimeData.hasUrls() : isLocal = True for url in mimeData.urls() : if url.toLocalFile().isEmpty() : isLocal = False if isLocal : ev.acceptProposedAction() def dropEvent( self, ev ) : if self.state != self.SELECTINGFILES : return mimeData = ev.mimeData() if mimeData.hasUrls() : for url in mimeData.urls() : f = url.toLocalFile() if not f.isEmpty() : self._addFile( str(f) ) self._onFileSelectionChanged() ev.acceptProposedAction() def _onAddClicked( self ) : defaultDir = os.path.expanduser( '~/Desktop' ) if not os.path.isdir(defaultDir) : defaultDir = '' openDir = localSettings().getString( 'Settings/FileSenderOpenDir' ) if (not openDir) or (not os.path.isdir(openDir)) : openDir = defaultDir fileList = QFileDialog.getOpenFileNames( self, 'Select file(s) to add...', openDir ) for f in fileList : self._addFile( str(f) ) if len(fileList) : openDir = os.path.split( str(fileList[0]) )[0] localSettings().setString( 'Settings/FileSenderOpenDir', openDir ) self._onFileSelectionChanged() def _onRemoveClicked( self ) : selItems = [ i for i in self.fileItems.keys() if self.ui.fileList.isItemSelected(i) ] for item in selItems : self._removeFile( item ) self._onFileSelectionChanged() def _onRemoveAllClicked( self ) : for item in self.fileItems.keys() : self._removeFile( item ) self._onFileSelectionChanged() def _onSendFilesClicked( self ) : self.setAcceptDrops( False ) self.ui.fileList.clearSelection() self.ui.fileList.setSelectionMode( QAbstractItemView.NoSelection ) self.ui.addFilesButton.setEnabled( False ) self.ui.removeFilesButton.setEnabled( False ) self.ui.removeAllButton.setEnabled( False ) self.ui.sendFilesButton.setEnabled( False ) self._doConnect() def _doConnect( self ) : def onConnect( connector ) : self.connectOp = None if connector.getError() != 0 : self._setError( 'Unable to connect to CSpace.' ) return self._doConnectUser( connector.getSock() ) self.connectOp = tcpConnect( ('127.0.0.1',env.port), self.reactor, onConnect ) self._setStatus( 'Connecting to CSpace...' ) self.state = self.CONNECTINGCSPACE def _doConnectUser( self, sock ) : self._setStatus( 'Connecting to %s...' % env.contactName ) self.state = self.CONNECTINGUSER def onConnect( err, sock ) : if err < 0 : self._setError( 'Error connecting to %s.' % env.contactName ) return self._doOfferFiles( sock ) connector = CSpaceConnector( sock, env.contactName, 'FileTransfer', self.reactor, onConnect ) self.connectOp = connector.getOp() def _doOfferFiles( self, sock ) : self._setStatus( 'Sending request ...' ) self.state = self.OFFERINGFILES fileList = [] for row in range(self.ui.fileList.count()) : item = self.ui.fileList.item( row ) fileList.append( self.fileItems[item][0] ) self.rpcConn = RPCConnection( sock, self.reactor ) self.switchboard = RPCSwitchboard( self.rpcConn ) self.fs = FlatFS( fileList ) self.fileServer = FileServer( self.fs, self.switchboard ) pending = {} for i,f in enumerate(fileList) : pending[os.path.split(f)[1].lower()] = i def onClose() : if pending : self._setError( 'Disconnected.' ) else : self._setStatus( 'Completed.' ) def onTransferStatus( payload ) : if type(payload) is not ListType : return if len(payload) != 4 : return for x in payload : if type(x) is not IntType : return if x < 0 : return fileId,numFiles,transferred,fileSize = payload if numFiles != len(fileList) : return if not (1 <= fileId <= numFiles) : return if transferred > fileSize : return fname = os.path.split(fileList[fileId-1])[1] lfname = fname.lower() pos = pending.get( lfname, None ) if pos is None : return if transferred == fileSize : percent = 100 del pending[lfname] else : percent = transferred*100 / fileSize self._setStatus( 'Sending file (%d/%d): %s (%d%%)' % (pos+1,len(fileList),fname,percent) ) self.switchboard.addOnewayAgent( 'TransferStatus', onTransferStatus ) self.rpcConn.setCloseCallback( onClose ) def closeEvent( self, ev ) : ev.accept() delaygc( self )
class FileSenderWindow(QWidget): SELECTINGFILES = 0 CONNECTINGCSPACE = 1 CONNECTINGUSER = 2 OFFERINGFILES = 3 def __init__(self, reactor): QWidget.__init__(self) self.ui = Ui_FileSenderWindow() self.ui.setupUi(self) self.reactor = reactor self._setStatus('Drag and drop files to be sent...') self.setWindowTitle(env.contactName + ' - ' + str(self.windowTitle())) self.setAcceptDrops(True) self.files = {} self.fileItems = {} self.connect(self.ui.fileList, SIGNAL('itemSelectionChanged()'), self._onFileSelectionChanged) self.connect(self.ui.addFilesButton, SIGNAL('clicked()'), self._onAddClicked) self.connect(self.ui.removeFilesButton, SIGNAL('clicked()'), self._onRemoveClicked) self.connect(self.ui.removeAllButton, SIGNAL('clicked()'), self._onRemoveAllClicked) self.connect(self.ui.sendFilesButton, SIGNAL('clicked()'), self._onSendFilesClicked) self.connect(self.ui.closeButton, SIGNAL('clicked()'), self.close) self.state = self.SELECTINGFILES def _setStatus(self, text, isError=False): lines = text.split('\n') text = '<b>%s</b>' % '<br>'.join(lines) if isError: text = '<font color=red>%s</font>' % text self.ui.status.setText(text) def _setError(self, text): self._setStatus(text, True) def _removeFile(self, item): info = self.fileItems.pop(item) self.ui.fileList.takeItem(self.ui.fileList.row(item)) fname = os.path.split(info[0])[1] del self.files[fname.lower()] if not self.files: self.ui.sendFilesButton.setEnabled(False) self.ui.removeAllButton.setEnabled(False) def _addFile(self, f): if not os.path.isfile(f): return False fname = os.path.split(f)[1] k = fname.lower() info = self.files.get(k, None) if info is not None: self._removeFile(info[1]) item = QListWidgetItem(fname, self.ui.fileList) info = [f, item] self.files[k] = info self.fileItems[item] = info self.ui.sendFilesButton.setEnabled(True) self.ui.removeAllButton.setEnabled(True) def _onFileSelectionChanged(self): if self.state != self.SELECTINGFILES: return selectCount = 0 for item in self.fileItems.keys(): if self.ui.fileList.isItemSelected(item): selectCount += 1 self.ui.removeFilesButton.setEnabled(selectCount > 0) def dragEnterEvent(self, ev): if self.state != self.SELECTINGFILES: return mimeData = ev.mimeData() if mimeData.hasUrls(): isLocal = True for url in mimeData.urls(): if url.toLocalFile().isEmpty(): isLocal = False if isLocal: ev.acceptProposedAction() def dropEvent(self, ev): if self.state != self.SELECTINGFILES: return mimeData = ev.mimeData() if mimeData.hasUrls(): for url in mimeData.urls(): f = url.toLocalFile() if not f.isEmpty(): self._addFile(str(f)) self._onFileSelectionChanged() ev.acceptProposedAction() def _onAddClicked(self): defaultDir = os.path.expanduser('~/Desktop') if not os.path.isdir(defaultDir): defaultDir = '' openDir = localSettings().getString('Settings/FileSenderOpenDir') if (not openDir) or (not os.path.isdir(openDir)): openDir = defaultDir fileList = QFileDialog.getOpenFileNames(self, 'Select file(s) to add...', openDir) for f in fileList: self._addFile(str(f)) if len(fileList): openDir = os.path.split(str(fileList[0]))[0] localSettings().setString('Settings/FileSenderOpenDir', openDir) self._onFileSelectionChanged() def _onRemoveClicked(self): selItems = [ i for i in self.fileItems.keys() if self.ui.fileList.isItemSelected(i) ] for item in selItems: self._removeFile(item) self._onFileSelectionChanged() def _onRemoveAllClicked(self): for item in self.fileItems.keys(): self._removeFile(item) self._onFileSelectionChanged() def _onSendFilesClicked(self): self.setAcceptDrops(False) self.ui.fileList.clearSelection() self.ui.fileList.setSelectionMode(QAbstractItemView.NoSelection) self.ui.addFilesButton.setEnabled(False) self.ui.removeFilesButton.setEnabled(False) self.ui.removeAllButton.setEnabled(False) self.ui.sendFilesButton.setEnabled(False) self._doConnect() def _doConnect(self): def onConnect(connector): self.connectOp = None if connector.getError() != 0: self._setError('Unable to connect to CSpace.') return self._doConnectUser(connector.getSock()) self.connectOp = tcpConnect(('127.0.0.1', env.port), self.reactor, onConnect) self._setStatus('Connecting to CSpace...') self.state = self.CONNECTINGCSPACE def _doConnectUser(self, sock): self._setStatus('Connecting to %s...' % env.contactName) self.state = self.CONNECTINGUSER def onConnect(err, sock): if err < 0: self._setError('Error connecting to %s.' % env.contactName) return self._doOfferFiles(sock) connector = CSpaceConnector(sock, env.contactName, 'FileTransfer', self.reactor, onConnect) self.connectOp = connector.getOp() def _doOfferFiles(self, sock): self._setStatus('Sending request ...') self.state = self.OFFERINGFILES fileList = [] for row in range(self.ui.fileList.count()): item = self.ui.fileList.item(row) fileList.append(self.fileItems[item][0]) self.rpcConn = RPCConnection(sock, self.reactor) self.switchboard = RPCSwitchboard(self.rpcConn) self.fs = FlatFS(fileList) self.fileServer = FileServer(self.fs, self.switchboard) pending = {} for i, f in enumerate(fileList): pending[os.path.split(f)[1].lower()] = i def onClose(): if pending: self._setError('Disconnected.') else: self._setStatus('Completed.') def onTransferStatus(payload): if type(payload) is not ListType: return if len(payload) != 4: return for x in payload: if type(x) is not IntType: return if x < 0: return fileId, numFiles, transferred, fileSize = payload if numFiles != len(fileList): return if not (1 <= fileId <= numFiles): return if transferred > fileSize: return fname = os.path.split(fileList[fileId - 1])[1] lfname = fname.lower() pos = pending.get(lfname, None) if pos is None: return if transferred == fileSize: percent = 100 del pending[lfname] else: percent = transferred * 100 / fileSize self._setStatus('Sending file (%d/%d): %s (%d%%)' % (pos + 1, len(fileList), fname, percent)) self.switchboard.addOnewayAgent('TransferStatus', onTransferStatus) self.rpcConn.setCloseCallback(onClose) def closeEvent(self, ev): ev.accept() delaygc(self)
class RouterClient( object ) : (CLOSED,CONNECTING,CONNECTED,REGISTERING,REGISTERED) = range(5) def __init__( self, routerAddr, reactor ) : self.routerAddr = routerAddr self.reactor = reactor self.state = self.CLOSED self.connectOp = None self.rpcConn = None self.pingOps = {} self.registerOp = None self.closeCallback = None def setCloseCallback( self, closeCallback ) : self.closeCallback = closeCallback def close( self ) : if self.state == self.CONNECTING : self.connectOp.cancel() self.connectOp = None else : for pingOp in self.pingOps.keys() : pingOp.cancel() self.pingOps.clear() if self.state == self.REGISTERING : self.registerOp.cancel() self.registerOp = None if self.state in (self.CONNECTED,self.REGISTERING,self.REGISTERED) : self.rpcConn.close() self.rpcConn = None self.state = self.CLOSED def enableIncoming( self, flag ) : assert self.state == self.REGISTERED self.rpcConn.allowIncoming( flag ) def setIncomingCallback( self, incomingCallback ) : assert self.state == self.REGISTERED self.incomingCallback = incomingCallback def getRouterAddr( self ) : return self.routerAddr def _onClose( self ) : self.close() if self.closeCallback : self.closeCallback() def connect( self, connectCallback ) : assert self.state == self.CLOSED def onTCPConnect( connector ) : self.connectOp = None if connector.getError() != 0 : self.state = self.CLOSED connectCallback( False ) return self.rpcConn = RPCConnection( connector.getSock(), self.reactor ) self.rpcConn.setCloseCallback( self._onClose ) self.state = self.CONNECTED connectCallback( True ) self.connectOp = tcpConnect( self.routerAddr, self.reactor, onTCPConnect ) self.state = self.CONNECTING def callPing( self, pingCallback ) : assert self.state in (self.CONNECTED,self.REGISTERING,self.REGISTERED) def onResult( err, result) : del self.pingOps[pingOp] if err < 0 : pingCallback( None ) return assert type(result) is list if (len(result) != 1) or (type(result[0]) is not list) : pingCallback( None ) return addr = tuple(result[0]) try : validateInetAddress( addr ) except : pingCallback( None ) return pingCallback( addr ) pingOp = _doRPCCall( self.rpcConn, 'Ping', [], onResult ) self.pingOps[pingOp] = 1 def callRegister( self, registerCallback, incomingCallback ) : assert self.state == self.CONNECTED def onResult( err, result ) : self.registerOp = None if err < 0 : self.state = self.CONNECTED registerCallback( None ) return if (len(result) != 1) or \ (type(result[0]) is not str) or (not result[0]) : self.state = self.CONNECTED registerCallback( None ) return self.state = self.REGISTERED self.routerId = result[0] self.rpcConn.setOnewayCallback( self._onOneway ) self.incomingCallback = incomingCallback registerCallback( self.routerId ) self.registerOp = _doRPCCall( self.rpcConn, 'Register', [], onResult ) self.state = self.REGISTERING def _onOneway( self, payload ) : assert self.state == self.REGISTERED print 'oneway payload =', payload if (type(payload) is not str) or (not payload) : return connectionId = payload self.incomingCallback( connectionId )
class FileReceiverWindow( QWidget, FlashWindow ) : def __init__( self, reactor ) : QWidget.__init__( self ) FlashWindow.__init__( self, reactor ) self.ui = Ui_FileReceiverWindow() self.ui.setupUi( self ) self.reactor = reactor self.setWindowTitle( env.displayName + ' - ' + str(self.windowTitle()) ) self.connect( self.ui.acceptButton, SIGNAL('clicked()'), self._onAcceptFiles ) self.connect( self.ui.cancelButton, SIGNAL('clicked()'), self.close ) tcpConnect( ('127.0.0.1',env.port), self.reactor, self._onConnect ) self._setStatus( 'Connecting to CSpace...' ) self.disconnected = False def _setStatus( self, text, isError=False ) : lines = text.split( '\n' ) text = '<b>%s</b>' % '<br/>'.join(lines) if isError : text = '<font color=red>%s</font>' % text self.ui.status.setText( text ) def _setError( self, text ) : self._setStatus( text, True ) self.ui.cancelButton.setText( '&Close' ) def _onConnect( self, connector ) : if connector.getError() != 0 : self._setError( 'Error connecting to CSpace.' ) return sock = connector.getSock() self._setStatus( 'Accepting connection from %s.' % env.displayName ) CSpaceAcceptor( sock, env.connectionId, self.reactor, self._onAccept ) def _onAccept( self, err, sock ) : if err < 0 : self._setError( 'Error accepting connection from %s.' % env.displayName ) return self.rpcConn = RPCConnection( sock, self.reactor ) self.fileClient = FileClient( self.rpcConn ) self._setStatus( 'Fetching file list from %s...' % env.displayName ) self.fileClient.callList( '/', self._onList ) def _onList( self, err, result ) : if err != 0 : self._setError( 'Error fetching file list from %s.' % env.displayName ) return self.files = [] for x in result : if not x.endswith('/') : self.files.append( x ) self.ui.fileList.addItem( x ) self._setStatus( ('%s is sending the following files.\n' % env.displayName ) + 'Would you like to accept?' ) self.ui.acceptButton.setEnabled( True ) self.rpcConn.setCloseCallback( self._onClose ) self.flash() def _onClose( self ) : self.disconnected = True self._setError( 'Disconnected.' ) self.ui.acceptButton.setEnabled( False ) def _chooseTargetDir( self ) : defaultDir = os.path.expanduser( '~/Desktop' ) if not os.path.isdir(defaultDir) : defaultDir = QString() dir = localSettings().getString( 'Settings/FileReceiverSaveDir' ) if (not dir) or (not os.path.isdir(dir)) : dir = defaultDir while True : dir = QFileDialog.getExistingDirectory( self, 'Choose directory to save the file(s)', dir ) if dir.isEmpty() : return None dir = str(dir) existing = [] for f in self.files : if os.path.exists(os.path.join(dir,f)) : existing.append(f) if not existing : break msg = 'The following file(s) already exist in\n%s.\nWould you like to overwrite?\n%s' % (dir,'\n'.join(existing)) result = QMessageBox.question( self, 'Overwrite Prompt', msg, QMessageBox.Yes, QMessageBox.No, QMessageBox.Cancel|QMessageBox.Escape ) if result == QMessageBox.Yes : break if result == QMessageBox.No : continue assert result == QMessageBox.Cancel return None localSettings().setString( 'Settings/FileReceiverSaveDir', dir ) return dir def _onAcceptFiles( self ) : self.ui.acceptButton.setEnabled( False ) targetDir = self._chooseTargetDir() if self.disconnected : return if not targetDir : self.ui.acceptButton.setEnabled( True ) return self.targetDir = targetDir self.curFileId = 0 self.rpcConn.setCloseCallback( None ) self.statusStub = RPCStub( self.rpcConn, 'TransferStatus' ) self._doTransfer() def _doTransfer( self ) : if self.curFileId >= len(self.files) : self._setStatus( 'Completed.' ) self.ui.cancelButton.setText( '&Close' ) self.rpcConn.close( deferred=True ) return fname = self.files[self.curFileId] self.curFileId += 1 self._setStatus( 'Receiving file(%d/%d): %s' % (self.curFileId,len(self.files),fname) ) remotePath = '/' + fname localPath = os.path.join( self.targetDir, fname ) try : self.fetcher = FileFetcher( self.fileClient, remotePath, localPath, self._onTransfer ) except (OSError, IOError), e : self._setError( 'Error saving file: %s' % localPath ) return