def onNegotiateSession(self, accepted, username, host, port): """ Callback method for incoming requests to start a peer-to-peer session. The username, host, and port of the requesting peer is provided as input. The value for 'accepted' is provided via a roundabout sequence of callback methods which poll for user input. """ logger.debug('onNegotiateCallback(accepted=%s, username=%s, host=%s, port=%d)' % (accepted, username, host, port)) if (not self.onNegotiateCallback == None) and (accepted == None) and (self.retryNegotiate == False): # we need user input on whether to accept, so we use chained callbacks to get that input # and end up back here with what we need deferredTrueNegotiate = defer.Deferred() sessionParams = { 'username': username, 'host': host, 'port': port } deferredTrueNegotiate.addCallback(self.onNegotiateSession, **sessionParams) self.onNegotiateCallback(deferredTrueNegotiate, username) if (accepted == True) or ((accepted == None) and self.retryNegotiate): # we havent rejected OR we are trying with a new IP address status_bar.status_message('trying to share with %s' % username) logger.info('Establishing session with %s at %s:%d' % (username, host, port)) logger.debug('accepted: %s, retryNegotiate: %s' % (accepted, self.retryNegotiate)) session = base.BasePeer(username, self.sendPeerFailedToConnect) session.clientConnect(host, port) self.negotiateCallback(session) elif accepted == False: status_bar.status_message('share with %s rejected!' % username) logger.info('Rejected session with %s at %s:%d' % (username, host, port)) self.msg(username, 'REJECTED')
def acceptSessionRequest(self, username, host, port): self.logger.debug('accepted session request from %s at %s:%d)' % (username, host, port)) status_bar.status_message('accepted session request from %s, trying to connect to %s:%d' % (username, host, port)) self.logger.info('Establishing session with %s at %s:%d' % (username, host, port)) session = basic.BasicPeer(username, self) session.clientConnect(host, port) registry.registerSession(session)
def clientConnectionLost(self, connector, reason): if error.ConnectionDone == reason.type: self.disconnect() else: # may want to reconnect, but for now lets print why logger.error('Connection lost: %s - %s' % (reason.type, reason.value)) status_bar.status_message('connection lost to %s' % self.str())
def connect(self, host, port, username, password, **kwargs): """ Connect to an instant messaging server. @param host: ip address or domain name of the host server @param port: C{int} port number of the host @param username: C{str} IM account username @param password: C{str} IM account password @param kwargs: {'channel': 'channelNameStringWoutPrefix'} @return: True on success """ assert kwargs.has_key('channel') if self.isConnected(): return # start a fresh connection if self.clientConnection: self.clientConnection.disconnect() # irc.IRCClient member setting self.nickname = username.encode() self.host = host.encode() self.port = port self.password = password.encode() self.channel = kwargs['channel'].encode() status_bar.status_message('connecting to %s' % self.str()) self.clientConnection = reactor.connectTCP(self.host, self.port, self)
def onNegotiateSession(self, accepted, username, host, port): """ Callback method for incoming requests to start a peer-to-peer session. The username, host, and port of the requesting peer is provided as input. The value for 'accepted' is provided via a roundabout sequence of callback methods which poll for user input. """ logger.debug( 'onNegotiateCallback(accepted=%s, username=%s, host=%s, port=%d)' % (accepted, username, host, port)) if (not self.onNegotiateCallback == None) and (accepted == None) and ( self.retryNegotiate == False): # we need user input on whether to accept, so we use chained callbacks to get that input # and end up back here with what we need deferredTrueNegotiate = defer.Deferred() sessionParams = {'username': username, 'host': host, 'port': port} deferredTrueNegotiate.addCallback(self.onNegotiateSession, **sessionParams) self.onNegotiateCallback(deferredTrueNegotiate, username) if (accepted == True) or ((accepted == None) and self.retryNegotiate): # we havent rejected OR we are trying with a new IP address status_bar.status_message('trying to share with %s' % username) logger.info('Establishing session with %s at %s:%d' % (username, host, port)) logger.debug('accepted: %s, retryNegotiate: %s' % (accepted, self.retryNegotiate)) session = base.BasePeer(username, self.sendPeerFailedToConnect) session.clientConnect(host, port) self.negotiateCallback(session) elif accepted == False: status_bar.status_message('share with %s rejected!' % username) logger.info('Rejected session with %s at %s:%d' % (username, host, port)) self.msg(username, 'REJECTED')
def connect(self, host, port, username, password, **kwargs): """ Connect to an instant messaging server. @param host: ip address or domain name of the host server @param port: C{int} port number of the host @param username: C{str} IM account username @param password: C{str} IM account password @param kwargs: {'channel': 'channelNameStringWoutPrefix'} @return: True on success """ assert kwargs.has_key('channel') if self.isConnected(): return # start a fresh connection if self.clientConnection: self.clientConnection.disconnect() # irc.IRCClient member setting self.nickname = username.encode() self.host = host.encode() self.port = port self.password = password.encode() self.channel = kwargs['channel'].encode() status_bar.status_message('connecting to %s' % self.str()) # self.clientConnection = reactor.connectTCP(self.host, self.port, self) self.clientConnection = reactor.connectSSL(self.host, self.port, self, ssl.ClientContextFactory())
def negotiateSession(self, username): """ Negotiate through the instant messaging layer a direct peer-to-peer connection with the user that has the given username. Note the username in question must represent another SubliminalCollaborator Negotiator instance used by another user. If the user identified by the given username is not in the C{Array} returned by listUsers(), the expectation is that successful execution of this function will result in the given username being added to the list of known users. """ if (not username in self.peerUsers) and (not username in self.unverifiedUsers): self.addUserToLists(username) if self.hostAddressToTryQueue == None or len( self.hostAddressToTryQueue) == 0: self.hostAddressToTryQueue = socket.gethostbyname_ex( socket.gethostname())[2] ipaddress = self.hostAddressToTryQueue.pop() session = basic.BasicPeer(username, self) port = session.hostConnect() self.logger.debug('attempting to start session with %s at %s:%d' % (username, ipaddress, port)) status_bar.status_message('trying to share with %s@%s' % (username, ipaddress)) self.pendingSession = session registry.registerSession(session) self.ctcpMakeQuery( username, [('DCC CHAT', '%s %s %d' % (base.DCC_PROTOCOL_COLLABORATE, ipaddress, port))])
def negotiateSession(self, username, tryNext=False): """ Negotiate through the instant messaging layer a direct peer-to-peer connection with the user that has the given username. Note the username in question must represent another SubliminalCollaborator Negotiator instance used by another user. If the user identified by the given username is not in the C{Array} returned by listUsers(), the expectation is that successful execution of this function will result in the given username being added to the list of known users. """ if (not username in self.peerUsers) and (not username in self.unverifiedUsers): self.addUserToLists(username) if not tryNext: self.hostAddressToTryQueue = socket.gethostbyname_ex(socket.gethostname())[2] if len(self.hostAddressToTryQueue) == 0: status_bar.status_message('failed to share with %s' % username) logger.warn('Unable to connect to peer %s, all host addresses tried and failed!' % username) # TODO error reporting in UI self.msg(username, 'NO-GOOD-HOST-IP') return ipaddress = self.hostAddressToTryQueue.pop() session = base.BasePeer(username) port = session.hostConnect() status_bar.status_message('trying to share with %s@%s' % (username, ipaddress)) logger.debug('Negotiating collab session with %s with ip address %s on port %d' % (username, ipaddress, port)) reactor.callFromThread(self.ctcpMakeQuery, username, [('DCC CHAT', 'collaborate %s %d' % (ipaddress, port))]) self.negotiateCallback(session)
def stopCollab(self): """ Notify the connected peer that we are terminating the collaborating session. """ if (self.peerType == interface.CLIENT) and (self.view != None): self.view.set_read_only(False) self.view = None status_bar.status_message('stopped sharing with %s' % self.str())
def clientConnectionLost(self, connector, reason): self.state = interface.STATE_DISCONNECTED if error.ConnectionDone == reason.type: self.disconnect() else: status_bar.status_message('lost share session with %s' % self.str()) # may want to reconnect, but for now lets print why logger.error('Connection lost: %s - %s' % (reason.type, reason.value))
def clientConnectionLost(self, connector, reason): if error.ConnectionDone == reason.type: self.disconnect() else: # may want to reconnect, but for now lets print why self.logger.error('Connection lost: %s - %s' % (reason.type, reason.value)) status_bar.status_message('connection lost to %s' % self.str())
def __init__(self): sublime_plugin.ApplicationCommand.__init__(self) irc.IRCNegotiator.negotiateCallback = self.openSession irc.IRCNegotiator.onNegotiateCallback = self.acceptSessionRequest irc.IRCNegotiator.rejectedOrFailedCallback = self.killHostedSession base.BasePeer.peerConnectedCallback = self.shareView base.BasePeer.peerRecvdViewCallback = self.addSharedView base.BasePeer.acceptSwapRole = self.acceptSwapRole status_bar.status_message('ready')
def clientConnectionLost(self, connector, reason): registry.removeSession(self) self.state = base.STATE_DISCONNECTED if error.ConnectionDone == reason.type: self.disconnect() else: status_bar.status_message('lost share session with %s' % self.str()) # may want to reconnect, but for now lets print why self.logger.error('Connection lost: %s - %s' % (reason.type, reason.value))
def connectAllChat(): logger.info('Connecting to all configured chat servers') chatClientKeys = chatClientConfig.keys() for connectedClient in negotiatorInstances.keys(): chatClientKeys.remove(connectedClient) for client in chatClientKeys: logger.info('Connecting to chat %s' % client) negotiatorInstances[client] = negotiatorFactoryMap[client.split('|', 1)[0]]() negotiatorInstances[client].connect(**chatClientConfig[client]) status_bar.status_message('connected clients: %d' % len(negotiatorInstances))
def acceptSessionRequest(self, username, host, port): self.logger.debug('accepted session request from %s at %s:%d)' % (username, host, port)) status_bar.status_message( 'accepted session request from %s, trying to connect to %s:%d' % (username, host, port)) self.logger.info('Establishing session with %s at %s:%d' % (username, host, port)) session = basic.BasicPeer(username, self) session.clientConnect(host, port) registry.registerSession(session)
def onDisconnect(self): """ Callback method if we are disconnected. """ if self.peerType == base.CLIENT: self.logger.debug('Disconnecting from peer at %s:%d' % (self.host, self.port)) else: self.logger.debug('Disconnecting from peer at %d' % self.port) self.disconnect() self.state = base.STATE_DISCONNECTED self.logger.info('Disconnected from peer %s' % self.sharingWithUser) status_bar.status_message('Stopped sharing with %s' % self.sharingWithUser)
def connectAllChat(): logger.info('Connecting to all configured chat servers') chatClientKeys = chatClientConfig.keys() for connectedClient in negotiatorInstances.keys(): chatClientKeys.remove(connectedClient) for client in chatClientKeys: logger.info('Connecting to chat %s' % client) negotiatorInstances[client] = negotiatorFactoryMap[client.split( '|', 1)[0]]() negotiatorInstances[client].connect(**chatClientConfig[client]) status_bar.status_message('connected clients: %d' % len(negotiatorInstances))
def onDisconnect(self): """ Callback method if we are disconnected. """ if self.peerType == interface.CLIENT: logger.debug('Disconnecting from peer at %s:%d' % (self.host, self.port)) else: logger.debug('Disconnecting from peer at %d' % self.port) self.disconnect() self.state = interface.STATE_DISCONNECTED logger.info('Disconnected from peer %s' % self.sharingWithUser) status_bar.status_message('Stopped sharing with %s' % self.sharingWithUser)
def disconnect(self): """ Disconnect from the instant messaging server. """ if self.clientConnection: if self.clientConnection.state == 'disconnected': return reactor.callFromThread(self.clientConnection.disconnect) logger.info('Disconnected from %s' % self.host) status_bar.status_message('disconnected from %s' % self.str()) self._registered = False self.peerUsers = None self.unverifiedUsers = None
def resyncCollab(self): """ Resync the shared editor contents between the host and the partner. """ status_bar.status_message('RESYNCING VIEW CONTENT WITH PEER') self.view.set_read_only(True) totalToSend = self.view.size() begin = 0 end = MAX_CHUNK_SIZE # now we make sure we are connected... better way to do this? while not self.state == interface.STATE_CONNECTED: time.sleep(1.0) if (self.state == interface.STATE_DISCONNECTING) or ( self.state == interface.STATE_DISCONNECTED): logger.error( 'While waiting to resync view over a connection the peer was disconnected!' ) self.disconnect() return view_name = self.view.file_name() if not view_name: view_name = self.view.name() logger.info('Resyncing view %s with %s' % (view_name, self.sharingWithUser)) self.toAck = [] self.sendMessage(interface.RESHARE_VIEW, payload=str(totalToSend)) while begin < totalToSend: chunkToSend = self.view.substr(sublime.Region(begin, end)) self.toAck.append(len(chunkToSend)) self.sendMessage(interface.VIEW_CHUNK, payload=chunkToSend) begin = begin + MAX_CHUNK_SIZE end = end + MAX_CHUNK_SIZE status_bar.progress_message( "sending view to %s" % self.sharingWithUser, begin, totalToSend) self.sendMessage(interface.END_OF_VIEW, payload=self.view.settings().get('syntax')) self.view.set_read_only(False) # send view position as it stands now so the partner view is positioned appropriately post-resync viewRegionLines = self.view.split_by_newlines( self.view.visible_region()) lineIdx = len(viewRegionLines) / 2 - 1 if lineIdx < 0: lineIdx = 0 viewCenterRegion = viewRegionLines[lineIdx] self.sendViewPositionUpdate(viewCenterRegion) # start the view monitoring thread if not already running if not self.viewMonitorThread.is_alive(): self.viewMonitorThread.start()
def connect(self): """ Connect to an instant messaging server. @return: True on success """ if self.isConnected(): return # start a fresh connection if self.clientConnection: self.clientConnection.disconnect() status_bar.status_message('connecting to %s' % self.str()) if self.useSSL: self.logger.info('connecting to %s with ssl' % self.str()) self.clientConnection = reactor.connectSSL(self.host, self.port, self, ssl.ClientContextFactory()) else: self.logger.info('connecting to %s' % self.str()) self.clientConnection = reactor.connectTCP(self.host, self.port, self)
def resyncCollab(self): """ Resync the shared editor contents between the host and the partner. """ status_bar.status_message('RESYNCING VIEW CONTENT WITH PEER') self.view.set_read_only(True) totalToSend = self.view.size() begin = 0 end = MAX_CHUNK_SIZE # now we make sure we are connected... better way to do this? while not self.state == interface.STATE_CONNECTED: time.sleep(1.0) if (self.state == interface.STATE_DISCONNECTING) or (self.state == interface.STATE_DISCONNECTED): logger.error('While waiting to resync view over a connection the peer was disconnected!') self.disconnect() return view_name = self.view.file_name() if not view_name: view_name = self.view.name() logger.info('Resyncing view %s with %s' % (view_name, self.sharingWithUser)) self.toAck = [] self.sendMessage(interface.RESHARE_VIEW, payload=str(totalToSend)) while begin < totalToSend: chunkToSend = self.view.substr(sublime.Region(begin, end)) self.toAck.append(len(chunkToSend)) self.sendMessage(interface.VIEW_CHUNK, payload=chunkToSend) begin = begin + MAX_CHUNK_SIZE end = end + MAX_CHUNK_SIZE status_bar.progress_message("sending view to %s" % self.sharingWithUser, begin, totalToSend) self.sendMessage(interface.END_OF_VIEW, payload=self.view.settings().get('syntax')) self.view.set_read_only(False) # send view position as it stands now so the partner view is positioned appropriately post-resync viewRegionLines = self.view.split_by_newlines(self.view.visible_region()) lineIdx = len(viewRegionLines) / 2 - 1 if lineIdx < 0: lineIdx = 0 viewCenterRegion = viewRegionLines[lineIdx] self.sendViewPositionUpdate(viewCenterRegion) # start the view monitoring thread if not already running if not self.viewMonitorThread.is_alive(): self.viewMonitorThread.start()
def connect(self): """ Connect to an instant messaging server. @return: True on success """ if self.isConnected(): return # start a fresh connection if self.clientConnection: self.clientConnection.disconnect() status_bar.status_message('connecting to %s' % self.str()) if self.useSSL: self.logger.info('connecting to %s with ssl' % self.str()) self.clientConnection = reactor.connectSSL( self.host, self.port, self, ssl.ClientContextFactory()) else: self.logger.info('connecting to %s' % self.str()) self.clientConnection = reactor.connectTCP(self.host, self.port, self)
def negotiateSession(self, username): """ Negotiate through the instant messaging layer a direct peer-to-peer connection with the user that has the given username. Note the username in question must represent another SubliminalCollaborator Negotiator instance used by another user. If the user identified by the given username is not in the C{Array} returned by listUsers(), the expectation is that successful execution of this function will result in the given username being added to the list of known users. """ if (not username in self.peerUsers) and (not username in self.unverifiedUsers): self.addUserToLists(username) if self.hostAddressToTryQueue == None or len(self.hostAddressToTryQueue) == 0: self.hostAddressToTryQueue = socket.gethostbyname_ex(socket.gethostname())[2] ipaddress = self.hostAddressToTryQueue.pop() session = basic.BasicPeer(username, self) port = session.hostConnect() self.logger.debug('attempting to start session with %s at %s:%d' % (username, ipaddress, port)) status_bar.status_message('trying to share with %s@%s' % (username, ipaddress)) self.pendingSession = session registry.registerSession(session) self.ctcpMakeQuery(username, [('DCC CHAT', '%s %s %d' % (base.DCC_PROTOCOL_COLLABORATE, ipaddress, port))])
def negotiateSession(self, username, tryNext=False): """ Negotiate through the instant messaging layer a direct peer-to-peer connection with the user that has the given username. Note the username in question must represent another SubliminalCollaborator Negotiator instance used by another user. If the user identified by the given username is not in the C{Array} returned by listUsers(), the expectation is that successful execution of this function will result in the given username being added to the list of known users. """ if (not username in self.peerUsers) and (not username in self.unverifiedUsers): self.addUserToLists(username) if not tryNext: self.hostAddressToTryQueue = socket.gethostbyname_ex( socket.gethostname())[2] if len(self.hostAddressToTryQueue) == 0: status_bar.status_message('failed to share with %s' % username) logger.warn( 'Unable to connect to peer %s, all host addresses tried and failed!' % username) # TODO error reporting in UI self.msg(username, 'NO-GOOD-HOST-IP') return ipaddress = self.hostAddressToTryQueue.pop() session = base.BasePeer(username) port = session.hostConnect() status_bar.status_message('trying to share with %s@%s' % (username, ipaddress)) logger.debug( 'Negotiating collab session with %s with ip address %s on port %d' % (username, ipaddress, port)) reactor.callFromThread(self.ctcpMakeQuery, username, [('DCC CHAT', 'collaborate %s %d' % (ipaddress, port))]) self.negotiateCallback(session)
def clientConnectionFailed(self, connector, reason): self.logger.error('Connection failed: %s - %s' % (reason.type, reason.value)) status_bar.status_message('connection failed to %s' % self.str()) self.connectionFailed = True self.disconnect()
def __init__(self): sublime_plugin.ApplicationCommand.__init__(self) sublime_plugin.EventListener.__init__(self) status_bar.status_message('ready')
def signedOn(self): # join the channel after we have connected # part of the Negotiator connection process status_bar.status_message('connected to %s' % self.str()) self.join(self.channel)
def clientConnectionFailed(self, connector, reason): logger.error('Connection failed: %s - %s' % (reason.type, reason.value)) status_bar.status_message('connection failed to %s' % self.str()) self.connectionFailed = True self.disconnect()
def signedOn(self): # join the channel after we have connected # part of the Negotiator connection process status_bar.status_message('connected to ' + self.str()) self.logger.info('Joining channel ' + self.channel) self.join(self.channel)