'connection tracking for TCP and UDP
finds or creates connection based on addr
updates connection with data if provided (using offset to reorder)
tracks timestamps if ts provided
extra args get passed to new connection objects'

def track(self, addr, data=None, ts=None, offset=None, **kwargs):

    conn = self.find(addr)
    if (not conn):
        if (self.swaplowport and (addr[0][1] < addr[1][1])):
            addr = (addr[1], addr[0])
        conn = Connection(self, addr=addr, ts=ts, **kwargs)
        if ('connectionInitHandler' in dir(self)):
            self.connectionInitHandler(conn)
        self.connectionsDict[addr] = conn
    if conn.stop:
        return False
    if data:
        if (addr == conn.addr):
            direction = 'cs'
        else:
            direction = 'sc'
        original_direction = conn.direction
        blob = conn.update(ts, direction, data, offset=offset)
        if (blob and self.isBlobHandlerPresent):
            self.blobHandler(conn, blob)
        if (self.maxblobs and (direction != original_direction) and (len(conn.blobs) >= self.maxblobs)):
            self.close(conn)
            return self.track(addr, ts=ts, **kwargs)
        if (not self.isConnectionHandlerPresent):
            while (len(conn.blobs) > 1):
                conn.blobs.pop(0)
    self.cleanup(ts)
    return conn
