Example #1
0
class ClientHandler(asyncore.dispatcher):
    """ Handles client connections. """
    def __init__(self, socket, server, database):
        asyncore.dispatcher.__init__(self, socket)

        # get a logger
        self.__logger = logging.getLogger("chattest.server.ClientHandler")
        self.__logger.debug("Created a new ClientHandler object...")

        # init member variables
        self.__state = ClientHandlerState(server, database, self)
        self.__ping_thread = PingThread(self)
        self.__message_generator = MessageGenerator()
        self.__message_parser = make_parser()
        self.__message_parser.setContentHandler(MessageParser(MessageHandler(self, database)))

        # client must first login
        self.buffer_send("/login")

        # start the ping thread
        self.update_ping(False)
        self.__ping_thread.start()

    def handle_expt(self):
        self.__logger.warn(self.get_username() + ": handle_expt")
        self.close()

    def handle_read(self):
        again = True
        while(again):
            try:
                command = self.recv(1024)
                self.__message_parser.feed(command)
                again = False
            except socket.error, err:
                if(err[0] == errno.EAGAIN):
                    again = True
                    continue

                self.__logger.warn(self.get_username() + ": read error - " + str(err))
                self.disconnect(False)
                break
            except SAXException, err:
                self.__logger.warn(self.get_username() + ": parse error - " + str(err))
                self.disconnect()
                break
            except MessageParserError, err:
                self.__logger.warn(self.get_username() + ": parse error - " + str(err))
                self.disconnect()
                break
Example #2
0
    def __init__(self, socket, server, database):
        asyncore.dispatcher.__init__(self, socket)

        # get a logger
        self.__logger = logging.getLogger("chattest.server.ClientHandler")
        self.__logger.debug("Created a new ClientHandler object...")

        # init member variables
        self.__state = ClientHandlerState(server, database, self)
        self.__ping_thread = PingThread(self)
        self.__message_generator = MessageGenerator()
        self.__message_parser = make_parser()
        self.__message_parser.setContentHandler(MessageParser(MessageHandler(self, database)))

        # client must first login
        self.buffer_send("/login")

        # start the ping thread
        self.update_ping(False)
        self.__ping_thread.start()
Example #3
0
class MumbleConnection:
  '''
     This class is responsible for implementing the underlying protocol
     of Mumble. It communicates with the server using protobuf messages.
  '''

  def __init__(self, connectionObserver, host, port, username, password):
    log.debug("Starting MumbleClient. Protocol Version: " + str(protocolVersion))
    self.host = host
    self.port = port
    self.username = username
    self.password = password
    self.isConnected = False
    self.pingThread=None
    self.chatList=[]
    self.session=None
    self.authenticated = False
    self.canSpeak = True
    self.currentChannel = -1
    self.channelList = []
    self.userList = []
    self.sockLock=thread.allocate_lock()
    self.CryptState = CryptState()
    self.send_queue = []
    self.stateLock = thread.allocate_lock()
    self.connectionObserver = connectionObserver
    self.disconnecting = False
    self.connectionObserver.setConnectionState(ConnectionState.Disconnected)
    self.codec = CODEC_NOCODEC

  def isConnected(self):
    return self.socket != None and self.isConnected

  def joinChannel(self, channelId):
    log.debug("Joining channel " + str(channelId))
    us = UserState()
    us.session=self.session
    us.channel_id=channelId
    try:
      self.sendMessage(MessageType.UserState, us)
      self.currentChannel=channelId
    except:
      log.error("Could not join channel")

  def sendMessage(self, messageType, message):
    packet=struct.pack(headerFormat,messageType,message.ByteSize())+message.SerializeToString()
    self.__sendRawPacket(packet)

  def __sendRawPacket(self, packet):
    self.sockLock.acquire()
    while len(packet)>0:
      sent=self.socket.send(packet)
      if sent < 0:
        log.error("Server socket error")
        self.sockLock.release()
        return
      packet=packet[sent:]
    self.sockLock.release()

  def sendUdpTunnelMessage(self, data):
    msgType = MessageType.UDPTunnel
    packet=struct.pack(headerFormat,msgType,len(data))+data
    self.__sendRawPacket(packet)

  def findChannel(self, channel_id):
    for c in self.channelList:
      if c['channel_id'] == channel_id:
        return c
    return None

  def __findUser(self, session_id):
    for u in self.userList:
      if u['session_id'] == session_id:
        return u
    return None

  def __readFully(self,size):
    msg=""
    while len(msg) < size:
      try:
        rcvd=self.socket.recv(size-len(msg))
      except Exception as inst:
        log.error("Recv error: ")
        log.error(inst)  
        return None
        #log.error("Error: " + type(inst) + " " + inst)
      msg += rcvd
      if len(rcvd)==0:
         log.warning("Got 0 bytes from socket. Strange.")
         return None
    return msg

  def __readThread(self):
    log.debug("Read thread started")
    msg = ""
    try:
      while self.isConnected:
        header=self.__readFully(6)
        if not header:
          log.debug("Didn't get header")
        msgType,length=struct.unpack(headerFormat, header)
        msg=self.__readFully(length)
        self.stateLock.acquire()
        try:
          self.__processMessage(msgType, msg)
        finally:
          self.stateLock.release()
    except Exception as e:
      log.error("Got exception: ")
      log.error(type(e))
      log.error(e.args)
      log.error(e)

  def __handleProtocol(self):
    self.stateLock.acquire()
    v = Version()
    v.version=protocolVersion
    v.release="mmb 0.0.1-dev"
    a = Authenticate()
    a.username=self.username
    if self.password != None:
      a.password=self.password
    a.celt_versions.append(-2147483637)
    log.debug("Sending Version message")
    self.sendMessage(MessageType.Version, v)
    log.debug("Sending Authenticate message")
    self.sendMessage(MessageType.Authenticate, a)
    self.stateLock.release()
    thread.start_new_thread(self.__readThread, ())

  def __processMessage(self, msgType, message):
    '''A message was received from the server, so process it.
       The msgType is the type of message that was received.
       The message is a ProtoBuf message that was received.
    '''

    log.debug("Processing Message...")
    log.debug(MessageType.StringLookupTable[msgType])
    if msgType == MessageType.UDPTunnel or msgType == MessageType.Ping:
      log.debug("Got Ping or UDPTunnel. Ignoring")
      return
    if msgType == MessageType.CodecVersion:
      oldCanSpeak = self.canSpeak
      cv = CodecVersion()
      cv.ParseFromString(message)   
      log.debug("alpha = " + str(cv.alpha))
      log.debug("beta = " + str(cv.beta))
      if cv.alpha != None and cv.alpha == supportedCodec:
        self.codec = CODEC_ALPHA
      elif cv.beta != None and cv.beta == supportedCodec:
        self.codec = CODEC_BETA
      self.canSpeak = self.canSpeak and (self.codec != CODEC_NOCODEC)
      if self.canSpeak != oldCanSpeak:
        self.connectionObserver.currentUserUpdated()
    elif msgType == MessageType.ServerSync:
      ss = ServerSync()
      ss.ParseFromString(message)
      self.session=ss.session
      self.authenticated = True
      u = self.__findUser(self.session)
      self.currentChannel = u['channel_id']
      self.pingThread = PingThread(self)
      self.pingThread.start()
      us = UserState()
      us.session=self.session
      self.connectionObserver.setConnectionState(ConnectionState.Connected)
      self.connectionObserver.serverSyncCompleted()
    elif msgType == MessageType.ChannelState:
      cs = ChannelState()
      cs.ParseFromString(message)
      c = self.findChannel(cs.channel_id)
      if c != None:
        c['name'] = cs.name
        return
      self.channelList.append({'channel_id':cs.channel_id,'name':cs.name})
    elif msgType == MessageType.ChannelRemove:
      cr = ChannelRemove()
      cr.ParseFromString(message)
      # to do
    elif msgType == MessageType.UserState:
      us = UserState()
      us.ParseFromString(message)
      u = self.__findUser(us.session)
      if u != None:
        if us.channel_id != None:
          u['channel_id'] = us.channel_id
          if us.session == self.session:
            self.currentChannel = u['channel_id']
        if us.session == self.session:
          if us.mute != None:
            self.canSpeak = not us.mute
          if us.suppress != None:
            self.canSpeak = not us.suppress
        return
      self.userList.append({'session_id':us.session,'name':us.name,'channel_id':us.channel_id})
    elif msgType == MessageType.UserRemove:
      pass
    elif msgType == MessageType.TextMessage:
      pass
    elif msgType == MessageType.Version:
      pass
    elif msgType == MessageType.ServerConfig:
      sc = ServerConfig()
      sc.ParseFromString(message)
      msgLength = sc.message_length
      if msgLength > 0:
        welcome_msg = self.__readFully(msgLength)
        log.debug(welcome_msg)
      imageMsgLength = sc.image_message_length
      if imageMsgLength > 0:
        welcome_image = self.__readFully(imageMsgLength)
    elif msgType == MessageType.CryptSetup:
      cs = CryptSetup()
      cs.ParseFromString(message)
      self.key = cs.key
      self.encrypt_iv = cs.server_nonce
      self.decrypt_iv = cs.client_nonce 
      if self.key != None and self.encrypt_iv != None and self.decrypt_iv != None:
        self.CryptState.setKey(self.key, self.encrypt_iv, self.decrypt_iv)
    else:
      log.debug("unhandled message type: " + str(msgType))

  def connect(self):
    log.debug("Attempting to connect...")
    tcpSock=socket.socket(type=socket.SOCK_STREAM)
    self.socket=ssl.wrap_socket(tcpSock,ssl_version=ssl.PROTOCOL_TLSv1)
    self.socket.setsockopt(socket.SOL_TCP,socket.TCP_NODELAY,1)
    try:
      self.socket.connect((self.host,self.port))
    except Exception as e:
      log.error(e)
      return
    log.debug("Connected.")
    self.isConnected = True
    self.connectionObserver.setConnectionState(ConnectionState.Connected)
    self.sockFD = self.socket.fileno()
    self.__handleProtocol()
   
  def disconnect(self):
    self.disconnecting = True
    self.stateLock.acquire()
    try:
   #   if self.readingThread != None:
      self.isConnected = False
    #    self.readingThread.join()
     #   self.readingThread = None
    except Exception as e:
      log.error(e)
    self.stateLock.release()

  def setComment(self, comment):
    log.debug("Setting comment to: " + comment)
    us = UserState()
    us.session = self.session
    us.comment = comment
    self.sendMessage(MessageType.UserState, us)
Example #4
0
  def __processMessage(self, msgType, message):
    '''A message was received from the server, so process it.
       The msgType is the type of message that was received.
       The message is a ProtoBuf message that was received.
    '''

    log.debug("Processing Message...")
    log.debug(MessageType.StringLookupTable[msgType])
    if msgType == MessageType.UDPTunnel or msgType == MessageType.Ping:
      log.debug("Got Ping or UDPTunnel. Ignoring")
      return
    if msgType == MessageType.CodecVersion:
      oldCanSpeak = self.canSpeak
      cv = CodecVersion()
      cv.ParseFromString(message)   
      log.debug("alpha = " + str(cv.alpha))
      log.debug("beta = " + str(cv.beta))
      if cv.alpha != None and cv.alpha == supportedCodec:
        self.codec = CODEC_ALPHA
      elif cv.beta != None and cv.beta == supportedCodec:
        self.codec = CODEC_BETA
      self.canSpeak = self.canSpeak and (self.codec != CODEC_NOCODEC)
      if self.canSpeak != oldCanSpeak:
        self.connectionObserver.currentUserUpdated()
    elif msgType == MessageType.ServerSync:
      ss = ServerSync()
      ss.ParseFromString(message)
      self.session=ss.session
      self.authenticated = True
      u = self.__findUser(self.session)
      self.currentChannel = u['channel_id']
      self.pingThread = PingThread(self)
      self.pingThread.start()
      us = UserState()
      us.session=self.session
      self.connectionObserver.setConnectionState(ConnectionState.Connected)
      self.connectionObserver.serverSyncCompleted()
    elif msgType == MessageType.ChannelState:
      cs = ChannelState()
      cs.ParseFromString(message)
      c = self.findChannel(cs.channel_id)
      if c != None:
        c['name'] = cs.name
        return
      self.channelList.append({'channel_id':cs.channel_id,'name':cs.name})
    elif msgType == MessageType.ChannelRemove:
      cr = ChannelRemove()
      cr.ParseFromString(message)
      # to do
    elif msgType == MessageType.UserState:
      us = UserState()
      us.ParseFromString(message)
      u = self.__findUser(us.session)
      if u != None:
        if us.channel_id != None:
          u['channel_id'] = us.channel_id
          if us.session == self.session:
            self.currentChannel = u['channel_id']
        if us.session == self.session:
          if us.mute != None:
            self.canSpeak = not us.mute
          if us.suppress != None:
            self.canSpeak = not us.suppress
        return
      self.userList.append({'session_id':us.session,'name':us.name,'channel_id':us.channel_id})
    elif msgType == MessageType.UserRemove:
      pass
    elif msgType == MessageType.TextMessage:
      pass
    elif msgType == MessageType.Version:
      pass
    elif msgType == MessageType.ServerConfig:
      sc = ServerConfig()
      sc.ParseFromString(message)
      msgLength = sc.message_length
      if msgLength > 0:
        welcome_msg = self.__readFully(msgLength)
        log.debug(welcome_msg)
      imageMsgLength = sc.image_message_length
      if imageMsgLength > 0:
        welcome_image = self.__readFully(imageMsgLength)
    elif msgType == MessageType.CryptSetup:
      cs = CryptSetup()
      cs.ParseFromString(message)
      self.key = cs.key
      self.encrypt_iv = cs.server_nonce
      self.decrypt_iv = cs.client_nonce 
      if self.key != None and self.encrypt_iv != None and self.decrypt_iv != None:
        self.CryptState.setKey(self.key, self.encrypt_iv, self.decrypt_iv)
    else:
      log.debug("unhandled message type: " + str(msgType))