Beispiel #1
0
def unpickleMethod(im_name,
                    im_self,
                    im_class):
    'support function for copy_reg to unpickle method refs'
    try:
        unbound = getattr(im_class,im_name)
        if im_self is None:
            return unbound
        bound=instancemethod(unbound.im_func,
                                 im_self,
                                 im_class)
        return bound
    except AttributeError:
        log.msg("Method",im_name,"not on class",im_class)
        assert im_self is not None,"No recourse: no instance to guess from."
        # Attempt a common fix before bailing -- if classes have
        # changed around since we pickled this method, we may still be
        # able to get it by looking on the instance's current class.
        unbound = getattr(im_self.__class__,im_name)
        log.msg("Attempting fixup with",unbound)
        if im_self is None:
            return unbound
        bound=instancemethod(unbound.im_func,
                                 im_self,
                                 im_self.__class__)
        return bound
Beispiel #2
0
    def doRead(self):
        """Called when my socket is ready for reading.

        This accepts a connection and calls self.protocol() to handle the
        wire-level protocol.
        """
        try:
            if platformType == "posix":
                numAccepts = self.numberAccepts
            else:
                # win32 event loop breaks if we do more than one accept()
                # in an iteration of the event loop.
                numAccepts = 1
            for i in range(numAccepts):
                # we need this so we can deal with a factory's buildProtocol
                # calling our loseConnection
                if self.disconnecting:
                    return
                try:
                    skt, addr = self.socket.accept()
                except socket.error, e:
                    if e.args[0] in (EWOULDBLOCK, EAGAIN):
                        self.numberAccepts = i
                        break
                    elif e.args[0] == EPERM:
                        # Netfilter on Linux may have rejected the
                        # connection, but we get told to try to accept()
                        # anyway.
                        continue
                    elif e.args[0] in (EMFILE, ENOBUFS, ENFILE, ENOMEM, ECONNABORTED):

                        # Linux gives EMFILE when a process is not allowed
                        # to allocate any more file descriptors.  *BSD and
                        # Win32 give (WSA)ENOBUFS.  Linux can also give
                        # ENFILE if the system is out of inodes, or ENOMEM
                        # if there is insufficient memory to allocate a new
                        # dentry.  ECONNABORTED is documented as possible on
                        # both Linux and Windows, but it is not clear
                        # whether there are actually any circumstances under
                        # which it can happen (one might expect it to be
                        # possible if a client sends a FIN or RST after the
                        # server sends a SYN|ACK but before application code
                        # calls accept(2), however at least on Linux this
                        # _seems_ to be short-circuited by syncookies.

                        log.msg("Could not accept new connection (%s)" % (
                            errorcode[e.args[0]],))
                        break
                    raise

                protocol = self.factory.buildProtocol(self._buildAddr(addr))
                if protocol is None:
                    skt.close()
                    continue
                s = self.sessionno
                self.sessionno = s+1
                transport = self.transport(skt, protocol, addr, self, s, self.reactor)
                transport = self._preMakeConnection(transport)
                protocol.makeConnection(transport)
            else:
Beispiel #3
0
    def reapProcess(self):
        """
        Try to reap a process (without blocking) via waitpid.

        This is called when sigchild is caught or a Process object loses its
        "connection" (stdout is closed) This ought to result in reaping all
        zombie processes, since it will be called twice as often as it needs
        to be.

        (Unfortunately, this is a slightly experimental approach, since
        UNIX has no way to be really sure that your process is going to
        go away w/o blocking.  I don't want to block.)
        """
        try:
            try:
                pid, status = os.waitpid(self.pid, os.WNOHANG)
            except OSError, e:
                if e.errno == errno.ECHILD:
                    # no child process
                    pid = None
                else:
                    raise
        except:
            log.msg('Failed to reap %d:' % self.pid)
            log.err()
            pid = None
        if pid:
            self.processEnded(status)
            unregisterReapProcessHandler(pid, self)
Beispiel #4
0
def unpickleModule(name):
    'support function for copy_reg to unpickle module refs'
    if oldModules.has_key(name):
        log.msg("Module has moved: %s" % name)
        name = oldModules[name]
        log.msg(name)
    return __import__(name,{},{},'x')
Beispiel #5
0
    def connectionLost(self, reason):
        """
        Cleans up the socket.
        """
        log.msg('(Port %s Closed)' % self._realPortNumber)
        self._realPortNumber = None
        d = None
        if hasattr(self, "deferred"):
            d = self.deferred
            del self.deferred

        base.BasePort.connectionLost(self, reason)
        self.connected = False
        self._closeSocket()
        del self.socket
        del self.fileno

        try:
            self.factory.doStop()
        except:
            self.disconnecting = False
            if d is not None:
                d.errback(failure.Failure())
            else:
                raise
        else:
            self.disconnecting = False
            if d is not None:
                d.callback(None)
Beispiel #6
0
 def __getstate__(self):
     log.msg( "WARNING: serializing ephemeral %s" % self )
     import gc
     if getattr(gc, 'get_referrers', None):
         for r in gc.get_referrers(self):
             log.msg( " referred to by %s" % (r,))
     return None
Beispiel #7
0
    def startListening(self):
        """Create and bind my socket, and begin listening on it.

        This is called on unserialization, and must be called after creating a
        server to begin listening on the specified port.
        """
        log.msg("%s starting on %r" % (self.factory.__class__, repr(self.port)))
        if self.wantPID:
            self.lockFile = lockfile.FilesystemLock(self.port + ".lock")
            if not self.lockFile.lock():
                raise CannotListenError, (None, self.port, "Cannot acquire lock")
            else:
                if not self.lockFile.clean:
                    try:
                        # This is a best-attempt at cleaning up
                        # left-over unix sockets on the filesystem.
                        # If it fails, there's not much else we can
                        # do.  The bind() below will fail with an
                        # exception that actually propegates.
                        if stat.S_ISSOCK(os.stat(self.port).st_mode):
                            os.remove(self.port)
                    except:
                        pass

        self.factory.doStart()
        try:
            skt = self.createInternetSocket()
            skt.bind(self.port)
        except socket.error, le:
            raise CannotListenError, (None, self.port, le)
Beispiel #8
0
 def _bindSocket(self):
     log.msg("%s starting on %s"%(self.protocol.__class__, repr(self.port)))
     try:
         skt = self.createInternetSocket() # XXX: haha misnamed method
         if self.port:
             skt.bind(self.port)
     except socket.error, le:
         raise error.CannotListenError, (None, self.port, le)
Beispiel #9
0
def logPacketData(data):
    lines = len(data)/16
    if lines*16 != len(data): lines=lines+1
    for i in range(lines):
        d = tuple(data[16*i:16*i+16])
        hex = map(lambda x: "%02X"%ord(x),d)
        text = map(lambda x: (len(repr(x))>3 and '.') or x, d)
        log.msg(' '.join(hex)+ ' '*3*(16-len(d)) +''.join(text))
    log.msg('')
Beispiel #10
0
    def doStart(self):
        """Make sure startFactory is called.

        Users should not call this function themselves!
        """
        if not self.numPorts:
            if self.noisy:
                log.msg("Starting factory %r" % self)
            self.startFactory()
        self.numPorts = self.numPorts + 1
Beispiel #11
0
    def doStart(self):
        """Make sure startProtocol is called.

        This will be called by makeConnection(), users should not call it.
        """
        if not self.numPorts:
            if self.noisy:
                log.msg("Starting protocol %s" % self)
            self.startProtocol()
        self.numPorts = self.numPorts + 1
Beispiel #12
0
 def oscar_Cookie(self,data):
     snac=readSNAC(data[1])
     if self.icq:
         i=snac[5].find("\000")
         snac[5]=snac[5][i:]
     tlvs=readTLVs(snac[5])
     if tlvs.has_key(6):
         self.cookie=tlvs[6]
         server,port=string.split(tlvs[5],":")
         d = self.connectToBOS(server, int(port))
         d.addErrback(lambda x: log.msg("Connection Failed! Reason: %s" % x))
         if self.deferred:
             d.chainDeferred(self.deferred)
         self.disconnect()
     elif tlvs.has_key(8):
         errorcode=tlvs[8]
         try:
             errorurl=tlvs[4]
         except KeyError:
             raise Exception('You are throttled for repeated logins')
         if errorcode=='\000\030':
             error="You are attempting to sign on again too soon.  Please try again later."
         elif errorcode=='\000\005':
             error="Invalid Username or Password."
         else: error=repr(errorcode)
         self.error(error,errorurl)
     else:
         log.msg('hmm, weird tlvs for %s cookie packet' % str(self))
         log.msg(tlvs)
         log.msg('snac')
         log.msg(str(snac))
     return "None"
Beispiel #13
0
    def __del__(self):
        """Print tracebacks and die.

        If the *last* (and I do mean *last*) callback leaves me in an error
        state, print a traceback (if said errback is a Failure).
        """
        if self.failResult is not None:
            log.msg("Unhandled error in Deferred:", isError=True)
            debugInfo = self._getDebugTracebacks()
            if debugInfo != '':
                log.msg("(debug: " + debugInfo + ")", isError=True)
            log.err(self.failResult)
Beispiel #14
0
    def doStop(self):
        """Make sure stopProtocol is called.

        This will be called by the port, users should not call it.
        """
        assert self.numPorts > 0
        self.numPorts = self.numPorts - 1
        self.transport = None
        if not self.numPorts:
            if self.noisy:
                log.msg("Stopping protocol %s" % self)
            self.stopProtocol()
Beispiel #15
0
    def dataReceived(self,data):
#        if isinstance(self, ChatService):
#            logPacketData(data)
        self.buf=self.buf+data
        flap=self.readFlap()
        while flap:
            func=getattr(self,"oscar_%s"%self.state,None)
            if not func:
                log.msg("no func for state: %s" % self.state)
            state=func(flap)
            if state:
                self.state=state
            flap=self.readFlap()
Beispiel #16
0
    def doStop(self):
        """Make sure stopFactory is called.

        Users should not call this function themselves!
        """
        if self.numPorts == 0:
            # this shouldn't happen, but does sometimes and this is better
            # than blowing up in assert as we did previously.
            return
        self.numPorts = self.numPorts - 1
        if not self.numPorts:
            if self.noisy:
                log.msg("Stopping factory %r" % self)
            self.stopFactory()
Beispiel #17
0
 def versionUpgrade(self):
     """(internal) Do a version upgrade.
     """
     bases = _aybabtu(self.__class__)
     # put the bases in order so superclasses' persistenceVersion methods
     # will be called first.
     bases.reverse()
     bases.append(self.__class__) # don't forget me!!
     # first let's look for old-skool versioned's
     if self.__dict__.has_key("persistenceVersion"):
         
         # Hacky heuristic: if more than one class subclasses Versioned,
         # we'll assume that the higher version number wins for the older
         # class, so we'll consider the attribute the version of the older
         # class.  There are obviously possibly times when this will
         # eventually be an incorrect assumption, but hopefully old-school
         # persistenceVersion stuff won't make it that far into multiple
         # classes inheriting from Versioned.
         
         pver = self.__dict__['persistenceVersion']
         del self.__dict__['persistenceVersion']
         highestVersion = 0
         highestBase = None
         for base in bases:
             if not base.__dict__.has_key('persistenceVersion'):
                 continue
             if base.persistenceVersion > highestVersion:
                 highestBase = base
                 highestVersion = base.persistenceVersion
         if highestBase:
             self.__dict__['%s.persistenceVersion' % reflect.qual(highestBase)] = pver
     for base in bases:
         # ugly hack, but it's what the user expects, really
         if (Versioned not in base.__bases__ and
             not base.__dict__.has_key('persistenceVersion')):
             continue
         currentVers = base.persistenceVersion
         pverName = '%s.persistenceVersion' % reflect.qual(base)
         persistVers = (self.__dict__.get(pverName) or 0)
         if persistVers:
             del self.__dict__[pverName]
         assert persistVers <=  currentVers, "Sorry, can't go backwards in time."
         while persistVers < currentVers:
             persistVers = persistVers + 1
             method = base.__dict__.get('upgradeToVersion%s' % persistVers, None)
             if method:
                 log.msg( "Upgrading %s (of %s @ %s) to version %s" % (reflect.qual(base), reflect.qual(self.__class__), id(self), persistVers) )
                 method(self)
             else:
                 log.msg( 'Warning: cannot upgrade %s to version %s' % (base, persistVers) )
Beispiel #18
0
 def connectionLost(self, reason=None):
     """Cleans up my socket.
     """
     log.msg('(Port %s Closed)' % repr(self.port))
     base.BasePort.connectionLost(self, reason)
     if hasattr(self, "protocol"):
         # we won't have attribute in ConnectedPort, in cases
         # where there was an error in connection process
         self.protocol.doStop()
     self.connected = 0
     self.socket.close()
     del self.socket
     del self.fileno
     if hasattr(self, "d"):
         self.d.callback(None)
         del self.d
Beispiel #19
0
 def _preenDescriptors(self):
     log.msg("Malformed file descriptor found.  Preening lists.")
     readers = self._reads.keys()
     writers = self._writes.keys()
     self._reads.clear()
     self._writes.clear()
     for selDict, selList in ((self._reads, readers),
                              (self._writes, writers)):
         for selectable in selList:
             try:
                 select.select([selectable], [selectable], [selectable], 0)
             except Exception, e:
                 log.msg("bad descriptor %s" % selectable)
                 self._disconnectSelectable(selectable, e, False)
             else:
                 selDict[selectable] = 1
Beispiel #20
0
 def _cbRequestSSI(self, snac, args = ()):
     if snac[1] == 0x0f: # same SSI as we have
         return
     itemdata = snac[5][3:]
     if args:
         revision, groups, permit, deny, permitMode, visibility = args
     else:
         version, revision = struct.unpack('!BH', snac[5][:3])
         groups = {}
         permit = []
         deny = []
         permitMode = None
         visibility = None
     while len(itemdata)>4:
         nameLength = struct.unpack('!H', itemdata[:2])[0]
         name = itemdata[2:2+nameLength]
         groupID, buddyID, itemType, restLength = \
             struct.unpack('!4H', itemdata[2+nameLength:10+nameLength])
         tlvs = readTLVs(itemdata[10+nameLength:10+nameLength+restLength])
         itemdata = itemdata[10+nameLength+restLength:]
         if itemType == 0: # buddies
             groups[groupID].addUser(buddyID, SSIBuddy(name, tlvs))
         elif itemType == 1: # group
             g = SSIGroup(name, tlvs)
             if groups.has_key(0): groups[0].addUser(groupID, g)
             groups[groupID] = g
         elif itemType == 2: # permit
             permit.append(name)
         elif itemType == 3: # deny
             deny.append(name)
         elif itemType == 4: # permit deny info
             if not tlvs.has_key(0xcb):
                 continue # this happens with ICQ
             permitMode = {1:'permitall',2:'denyall',3:'permitsome',4:'denysome',5:'permitbuddies'}[ord(tlvs[0xca])]
             visibility = {'\xff\xff\xff\xff':'all','\x00\x00\x00\x04':'notaim'}[tlvs[0xcb]]
         elif itemType == 5: # unknown (perhaps idle data)?
             pass
         else:
             log.msg('%s %s %s %s %s' % (name, groupID, buddyID, itemType, tlvs))
     timestamp = struct.unpack('!L',itemdata)[0]
     if not timestamp: # we've got more packets coming
         # which means add some deferred stuff
         d = defer.Deferred()
         self.requestCallbacks[snac[4]] = d
         d.addCallback(self._cbRequestSSI, (revision, groups, permit, deny, permitMode, visibility))
         return d
     return (groups[0].users,permit,deny,permitMode,visibility,timestamp,revision)
Beispiel #21
0
    def mainLoop(self):
        while self._started:
            try:
                while self._started:
                    # Advance simulation time in delayed event
                    # processors.
                    self.runUntilCurrent()

                    # XXX f**k this shit.. WHY does twisted's select()
                    # block signals? this is NOT NORMAL
                    self.doIteration(1)

                    #t2 = self.timeout()
                    #t = self.running and t2
                    #self.doIteration(t)
            except:
                log.msg("Unexpected error in main loop.")
                log.err()
            else:
                log.msg('Main loop terminated.')
Beispiel #22
0
def registerReapProcessHandler(pid, process):
    """
    Register a process handler for the given pid, in case L{reapAllProcesses}
    is called.

    @param pid: the pid of the process.
    @param process: a process handler.
    """
    if pid in reapProcessHandlers:
        raise RuntimeError("Try to register an already registered process.")
    try:
        auxPID, status = os.waitpid(pid, os.WNOHANG)
    except:
        log.msg('Failed to reap %d:' % pid)
        log.err()
        auxPID = None
    if auxPID:
        process.processEnded(status)
    else:
        # if auxPID is 0, there are children but none have exited
        reapProcessHandlers[pid] = process
Beispiel #23
0
    def retry(self, connector=None):
        """Have this connector connect again, after a suitable delay.
        """
        if not self.continueTrying:
            if self.noisy:
                log.msg("Abandoning %s on explicit request" % (connector,))
            return

        if connector is None:
            if self.connector is None:
                raise ValueError("no connector to retry")
            else:
                connector = self.connector

        self.retries += 1
        if self.maxRetries is not None and (self.retries > self.maxRetries):
            if self.noisy:
                log.msg("Abandoning %s after %d retries." %
                        (connector, self.retries))
            return

        self.delay = min(self.delay * self.factor, self.maxDelay)
        if self.jitter:
            self.delay = random.normalvariate(self.delay,
                                              self.delay * self.jitter)

        if self.noisy:
            log.msg("%s will retry in %d seconds" % (connector, self.delay,))
        from include.twisted.internet import reactor

        def reconnector():
            self._callID = None
            connector.connect()
        self._callID = reactor.callLater(self.delay, reconnector)
Beispiel #24
0
    def _handleSignals(self):
        """
        Install the signal handlers for the Twisted event loop.
        """
        try:
            import signal
        except ImportError:
            log.msg("Warning: signal module unavailable -- "
                    "not installing signal handlers.")
            return

        if signal.getsignal(signal.SIGINT) == signal.default_int_handler:
            # only handle if there isn't already a handler, e.g. for Pdb.
            signal.signal(signal.SIGINT, self.sigInt)
        signal.signal(signal.SIGTERM, self.sigTerm)

        # Catch Ctrl-Break in windows
        if hasattr(signal, "SIGBREAK"):
            signal.signal(signal.SIGBREAK, self.sigBreak)

        if platformType == 'posix':
            signal.signal(signal.SIGCHLD, self._handleSigchld)
Beispiel #25
0
 def oscar_unknown(self,snac):
     log.msg("unknown for %s" % self)
     log.msg(snac)
Beispiel #26
0
    def oscar_04_07(self, snac):
        """
        ICBM message (instant message)
        """
        data = snac[3]
        cookie, data = data[:8], data[8:]
        channel = struct.unpack('!H',data[:2])[0]
        data = data[2:]
        user, data = self.parseUser(data, 1)
        tlvs = readTLVs(data)
        if channel == 1: # message
            flags = []
            multiparts = []
            for k, v in tlvs.items():
                if k == 2:
                    while v:
                        v = v[2:] # skip bad data
                        messageLength, charSet, charSubSet = struct.unpack('!3H', v[:6])
                        messageLength -= 4
                        message = [v[6:6+messageLength]]
                        if charSet == 0:
                            pass # don't add anything special
                        elif charSet == 2:
                            message.append('unicode')
                        elif charSet == 3:
                            message.append('iso-8859-1')
                        elif charSet == 0xffff:
                            message.append('none')
                        if charSubSet == 0xb:
                            message.append('macintosh')
                        if messageLength > 0: multiparts.append(tuple(message))
                        v = v[6+messageLength:]
                elif k == 3:
                    flags.append('acknowledge')
                elif k == 4:
                    flags.append('auto')
                elif k == 6:
                    flags.append('offline')
                elif k == 8:
                    iconLength, foo, iconSum, iconStamp = struct.unpack('!LHHL',v)
                    if iconLength:
                        flags.append('icon')
                        flags.append((iconLength, iconSum, iconStamp))
                elif k == 9:
                    flags.append('buddyrequest')
                elif k == 0xb: # unknown
                    pass
                elif k == 0x17:
                    flags.append('extradata')
                    flags.append(v)
                else:
                    log.msg('unknown TLV for incoming IM, %04x, %s' % (k,repr(v)))

#  unknown tlv for user SNewdorf
#  t: 29
#  v: '\x00\x00\x00\x05\x02\x01\xd2\x04r\x00\x01\x01\x10/\x8c\x8b\x8a\x1e\x94*\xbc\x80}\x8d\xc4;\x1dEM'
# XXX what is this?
            self.receiveMessage(user, multiparts, flags)
        elif channel == 2: # rondevouz
            status = struct.unpack('!H',tlvs[5][:2])[0]
            requestClass = tlvs[5][10:26]
            moreTLVs = readTLVs(tlvs[5][26:])
            if requestClass == CAP_CHAT: # a chat request
                exchange = struct.unpack('!H',moreTLVs[10001][:2])[0]
                name = moreTLVs[10001][3:-2]
                instance = struct.unpack('!H',moreTLVs[10001][-2:])[0]
                if not self.services.has_key(SERVICE_CHATNAV):
                    self.connectService(SERVICE_CHATNAV,1).addCallback(lambda x: self.services[SERVICE_CHATNAV].getChatInfo(exchange, name, instance).\
                        addCallback(self._cbGetChatInfoForInvite, user, moreTLVs[12]))
                else:
                    self.services[SERVICE_CHATNAV].getChatInfo(exchange, name, instance).\
                        addCallback(self._cbGetChatInfoForInvite, user, moreTLVs[12])
            elif requestClass == CAP_SEND_FILE:
                if moreTLVs.has_key(11): # cancel
                    log.msg('cancelled file request')
                    log.msg(status)
                    return # handle this later
                name = moreTLVs[10001][9:-7]
                desc = moreTLVs[12]
                log.msg('file request from %s, %s, %s' % (user, name, desc))
                self.receiveSendFileRequest(user, name, desc, cookie)
            else:
                log.msg('unsupported rondevouz: %s' % requestClass)
                log.msg(repr(moreTLVs))
        else:
            log.msg('unknown channel %02x' % channel)
            log.msg(tlvs)
Beispiel #27
0
 def initDone(self):
     """
     called when we get the rate information, which means we should do other init. stuff.
     """
     log.msg('%s initDone' % self)
     pass
Beispiel #28
0
 def updateBuddy(self, user):
     """
     called when a buddy changes status, with the OSCARUser for that buddy.
     """
     log.msg('%s updateBuddy %s' % (self, user))
     pass
Beispiel #29
0
 def offlineBuddy(self, user):
     """
     called when a buddy goes offline
     """
     log.msg('%s offlineBuddy %s' % (self, user))
     pass
Beispiel #30
0
 def __init__(self, name, warn, tlvs):
     self.name = name
     self.warning = warn
     self.flags = []
     self.caps = []
     for k,v in tlvs.items():
         if k == 1: # user flags
             v=struct.unpack('!H',v)[0]
             for o, f in [(1,'trial'),
                          (2,'unknown bit 2'),
                          (4,'aol'),
                          (8,'unknown bit 4'),
                          (16,'aim'),
                          (32,'away'),
                          (1024,'activebuddy')]:
                 if v&o: self.flags.append(f)
         elif k == 2: # member since date
             self.memberSince = struct.unpack('!L',v)[0]
         elif k == 3: # on-since
             self.onSince = struct.unpack('!L',v)[0]
         elif k == 4: # idle time
             self.idleTime = struct.unpack('!H',v)[0]
         elif k == 5: # unknown
             pass
         elif k == 6: # icq online status
             if v[2] == '\x00':
                 self.icqStatus = 'online'
             elif v[2] == '\x01':
                 self.icqStatus = 'away'
             elif v[2] == '\x02':
                 self.icqStatus = 'dnd'
             elif v[2] == '\x04':
                 self.icqStatus = 'out'
             elif v[2] == '\x10':
                 self.icqStatus = 'busy'
             else:
                 self.icqStatus = 'unknown'
         elif k == 10: # icq ip address
             self.icqIPaddy = socket.inet_ntoa(v)
         elif k == 12: # icq random stuff
             self.icqRandom = v
         elif k == 13: # capabilities
             caps=[]
             while v:
                 c=v[:16]
                 if c==CAP_ICON: caps.append("icon")
                 elif c==CAP_IMAGE: caps.append("image")
                 elif c==CAP_VOICE: caps.append("voice")
                 elif c==CAP_CHAT: caps.append("chat")
                 elif c==CAP_GET_FILE: caps.append("getfile")
                 elif c==CAP_SEND_FILE: caps.append("sendfile")
                 elif c==CAP_SEND_LIST: caps.append("sendlist")
                 elif c==CAP_GAMES: caps.append("games")
                 else: caps.append(("unknown",c))
                 v=v[16:]
             caps.sort()
             self.caps=caps
         elif k == 14: pass
         elif k == 15: # session length (aim)
             self.sessionLength = struct.unpack('!L',v)[0]
         elif k == 16: # session length (aol)
             self.sessionLength = struct.unpack('!L',v)[0]
         elif k == 30: # no idea
             pass
         else:
             log.msg("unknown tlv for user %s\nt: %s\nv: %s"%(self.name,k,repr(v)))