예제 #1
0
파일: http.c 프로젝트: Amelos/moloch
void moloch_http_do_requests(MolochHttp_t *server)
{
    // Something waiting
    while (DLL_COUNT(r_, &server->requestQ)) {

        // No free connections
        if (DLL_COUNT(e_, &server->connQ) == 0) {

            // Not at our max, create one a second
            if (server->numConns < server->maxConns && time(0) - server->lastFailedConnect > 0) {
                moloch_http_create(server, FALSE);
            }
            return;
        }

        // Have a free conn and a request
        MolochConn_t *conn;
        DLL_POP_HEAD(e_, &server->connQ, conn);
        DLL_POP_HEAD(r_, &server->requestQ, conn->request);
        server->inProgress++;
        if (!moloch_http_process_send(conn, FALSE)) {
            server->inProgress--;
            LOG("ERROR - %p: Couldn't send %.*s", (void*)conn, conn->request->key_len, conn->request->key);
            DLL_PUSH_HEAD(r_, &server->requestQ, conn->request);

            moloch_http_free_conn(conn, FALSE);
        }
    }
}
예제 #2
0
MolochSimple_t *writer_simple_alloc(int thread, MolochSimple_t *previous)
{
    MolochSimple_t *info;

    MOLOCH_LOCK(freeList[thread].lock);
    DLL_POP_HEAD(simple_, &freeList[thread], info);
    MOLOCH_UNLOCK(freeList[thread].lock);

    if (!info) {
        info = MOLOCH_TYPE_ALLOC0(MolochSimple_t);
        info->buf = mmap (0, config.pcapWriteSize + MOLOCH_PACKET_MAX_LEN, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
        info->thread = thread;
    } else {
        info->bufpos = 0;
        info->closing = 0;
    }

    if (previous) {
        info->file = previous->file;
    } else {
        info->file = MOLOCH_TYPE_ALLOC0(MolochSimpleFile_t);
        switch(simpleMode) {
        case MOLOCH_SIMPLE_NORMAL:
            break;
        case MOLOCH_SIMPLE_XOR2048:
            break;
        case MOLOCH_SIMPLE_AES256CTR:
            info->file->cipher_ctx = EVP_CIPHER_CTX_new();
            break;
        }
    }
    return info;
}
예제 #3
0
void *writer_simple_thread(void *UNUSED(arg))
{
    MolochSimple_t *info;

    LOG("THREAD %p", (gpointer)pthread_self());
    while (1) {
        MOLOCH_LOCK(simpleQ);
        while (DLL_COUNT(simple_, &simpleQ) == 0) {
            MOLOCH_COND_WAIT(simpleQ);
        }
        DLL_POP_HEAD(simple_, &simpleQ, info);
        MOLOCH_UNLOCK(simpleQ);

        uint32_t pos = 0;
        uint32_t total;
        if (info->closing) {
            total = info->bufpos;
            if (total % pageSize != 0) {
                total = (total - (total % pageSize) + pageSize);
            }
        } else {
            total = config.pcapWriteSize;
        }

        switch(simpleMode) {
        case MOLOCH_SIMPLE_NORMAL:
            break;
        case MOLOCH_SIMPLE_XOR2048: {
            uint32_t i;
            for (i = 0; i < total; i++)
                info->buf[i] ^= info->file->dek[i % 256];
            break;
        }
        case MOLOCH_SIMPLE_AES256CTR: {
            int outl;
            if (!EVP_EncryptUpdate(info->file->cipher_ctx, (uint8_t *)info->buf, &outl, (uint8_t *)info->buf, total))
                LOGEXIT("Encrypting data failed");
            if ((int)total != outl)
                LOGEXIT("Encryption in (%d) and out (%d) didn't match", total, outl);
            break;
        }
        }

        while (pos < total) {
            int len = write(info->file->fd, info->buf + pos, total - pos);
            if (len >= 0) {
                pos += len;
            } else {
                LOGEXIT("ERROR writing - %d %s", len, strerror(errno));
            }
        }
        if (info->closing) {
            ftruncate(info->file->fd, info->file->pos);
            close(info->file->fd);
        }

        writer_simple_free(info);
    }
    return NULL;
}
예제 #4
0
void moloch_packet_tcp_free(MolochSession_t *session)
{
    MolochTcpData_t *td;
    while (DLL_POP_HEAD(td_, &session->tcpData, td)) {
        moloch_packet_free(td->packet);
        MOLOCH_TYPE_FREE(MolochTcpData_t, td);
    }
}
예제 #5
0
파일: http.c 프로젝트: doduytrung/moloch
static gboolean moloch_http_send_timer_callback(gpointer UNUSED(unused))
{
    MolochHttpRequest_t       *request;

    while (1) {
        MOLOCH_LOCK(requests);
        DLL_POP_HEAD(rqt_, &requests, request);
        if (!request) {
            requestsTimer = 0;
            MOLOCH_UNLOCK(requests);
            return G_SOURCE_REMOVE;
        }
        MOLOCH_UNLOCK(requests);

        curl_multi_add_handle(request->server->multi, request->easy);
    }

    return G_SOURCE_REMOVE;
}
예제 #6
0
파일: http.c 프로젝트: LubyRuffy/moloch
static gboolean moloch_http_send_timer_callback(gpointer UNUSED(unused))
{
    MolochHttpRequest_t       *request;

    while (1) {
        MOLOCH_LOCK(requests);
        DLL_POP_HEAD(rqt_, &requests, request);
        if (!request) {
            requestsTimer = 0;
            MOLOCH_UNLOCK(requests);
            return G_SOURCE_REMOVE;
        }
        MOLOCH_UNLOCK(requests);

#ifdef MOLOCH_HTTP_DEBUG
        LOG("HTTPDEBUG DO %s %p %d %s", request->server->names[0], request, request->server->outstanding, request->url);
#endif
        curl_multi_add_handle(request->server->multi, request->easy);
    }

    return G_SOURCE_REMOVE;
}
예제 #7
0
파일: http.c 프로젝트: ariosx/moloch
void moloch_http_free_server(void *serverV)
{
    MolochHttp_t *server = serverV;

    int q;
    for (q = 0; q < 2; q++) {
        while (server->requestQ[q].r_count > 0 || server->connQ.e_count != server->maxConns) {
            g_main_context_iteration (g_main_context_default(), FALSE);
        }
    }

    MolochConn_t *es = 0;
    while (DLL_POP_HEAD(e_, &server->connQ, es)) {
        MOLOCH_TYPE_FREE(MolochConn_t, es);
    }

    MOLOCH_TYPE_FREE(MolochConn_t, server->syncConn);
    server->syncConn = 0;
    g_strfreev(server->names);

    MOLOCH_TYPE_FREE(MolochHttp_t, server);
}
예제 #8
0
파일: http.c 프로젝트: Amelos/moloch
void moloch_http_free_server(void *serverV)
{
    MolochHttp_t *server = serverV;
    int n=0;

    while (server->requestQ.r_count > 0 || server->inProgress > 0) {
        n++;
        if (n%10000 == 0)
            LOG("%s %d %d", server->names[0], server->requestQ.r_count, server->inProgress);
        g_main_context_iteration (g_main_context_default(), FALSE);
    }

    MolochConn_t *conn = 0;
    while (DLL_POP_HEAD(e_, &server->connQ, conn)) {
        moloch_http_free_conn(conn, FALSE);
    }

    moloch_http_free_conn(server->syncConn, FALSE);
    server->syncConn = 0;
    g_strfreev(server->names);

    MOLOCH_TYPE_FREE(MolochHttp_t, server);
}
예제 #9
0
int reader_libpcapfile_next()
{
    char         errbuf[1024];
    gchar       *fullfilename;

    pcap = 0;

    if (config.pcapReadFiles) {
        static int pcapFilePos = 0;

        fullfilename = config.pcapReadFiles[pcapFilePos];

        errbuf[0] = 0;
        if (!fullfilename) {
            goto filesDone;
        }
        pcapFilePos++;

        LOG ("Processing %s", fullfilename);
        pcap = pcap_open_offline(fullfilename, errbuf);

        if (!pcap) {
            LOG("Couldn't process '%s' error '%s'", fullfilename, errbuf);
            return reader_libpcapfile_next();
        }
        if (!realpath(fullfilename, offlinePcapFilename)) {
            LOG("ERROR - pcap open failed - Couldn't realpath file: '%s' with %d", fullfilename, errno);
            exit(1);
        }

        reader_libpcapfile_opened();
        return 1;
    }

filesDone:

    if (config.pcapReadDirs) {
        static int   pcapDirPos = 0;
        static GDir *pcapGDir[21];
        static char *pcapBase[21];
        static int   pcapGDirLevel = -1;
        GError      *error = 0;

        if (pcapGDirLevel == -2) {
            goto dirsDone;
        }

        if (pcapGDirLevel == -1) {
            pcapGDirLevel = 0;
            pcapBase[0] = config.pcapReadDirs[pcapDirPos];
            if (!pcapBase[0]) {
                pcapGDirLevel = -2;
                goto dirsDone;
            }
        }

        if (!pcapGDir[pcapGDirLevel]) {
            pcapGDir[pcapGDirLevel] = g_dir_open(pcapBase[pcapGDirLevel], 0, &error);
            if (error) {
                LOG("ERROR: Couldn't open pcap directory: Receive Error: %s", error->message);
                exit(0);
            }
        }
        const gchar *filename;
        while (1) {
            filename = g_dir_read_name(pcapGDir[pcapGDirLevel]);

            // No more files, stop processing this directory
            if (!filename) {
                break;
            }

            // Skip hidden files/directories
            if (filename[0] == '.')
                continue;

            fullfilename = g_build_filename (pcapBase[pcapGDirLevel], filename, NULL);

            // If recursive option and a directory then process all the files in that dir
            if (config.pcapRecursive && g_file_test(fullfilename, G_FILE_TEST_IS_DIR)) {
                if (pcapGDirLevel >= 20)
                    continue;
                pcapBase[pcapGDirLevel+1] = fullfilename;
                pcapGDirLevel++;
                return reader_libpcapfile_next();
            }

            if (!g_regex_match(config.offlineRegex, filename, 0, NULL)) {
                g_free(fullfilename);
                continue;
            }

            if (!realpath(fullfilename, offlinePcapFilename)) {
                g_free(fullfilename);
                continue;
            }

            if (config.pcapSkip && moloch_db_file_exists(offlinePcapFilename)) {
                if (config.debug)
                    LOG("Skipping %s", fullfilename);
                g_free(fullfilename);
                continue;
            }

            LOG ("Processing %s", fullfilename);
            errbuf[0] = 0;
            pcap = pcap_open_offline(fullfilename, errbuf);
            if (!pcap) {
                LOG("Couldn't process '%s' error '%s'", fullfilename, errbuf);
                g_free(fullfilename);
                continue;
            }
            reader_libpcapfile_opened();
            g_free(fullfilename);
            return 1;
        }
        g_dir_close(pcapGDir[pcapGDirLevel]);
        pcapGDir[pcapGDirLevel] = 0;

        if (pcapGDirLevel > 0) {
            g_free(pcapBase[pcapGDirLevel]);
            pcapGDirLevel--;
            return reader_libpcapfile_next();
        } else {
            pcapDirPos++;
            pcapGDirLevel = -1;
            return reader_libpcapfile_next();
        }

    }

dirsDone:
    while (DLL_COUNT(s_, &monitorQ) > 0) {
        MolochString_t *string;
        DLL_POP_HEAD(s_, &monitorQ, string);
        fullfilename = string->str;
        MOLOCH_TYPE_FREE(MolochString_t, string);

        if (!realpath(fullfilename, offlinePcapFilename)) {
            g_free(fullfilename);
            continue;
        }

        if (config.pcapSkip && moloch_db_file_exists(offlinePcapFilename)) {
            if (config.debug)
                LOG("Skipping %s", fullfilename);
            g_free(fullfilename);
            continue;
        }

        LOG ("Processing %s", fullfilename);
        errbuf[0] = 0;
        pcap = pcap_open_offline(fullfilename, errbuf);
        if (!pcap) {
            LOG("Couldn't process '%s' error '%s'", fullfilename, errbuf);
            g_free(fullfilename);
            continue;
        }
        reader_libpcapfile_opened();
        g_free(fullfilename);
        return 1;
    }
    return 0;
}
예제 #10
0
LOCAL int reader_libpcapfile_next()
{
    gchar       *fullfilename;

    pcap = 0;

    if (config.pcapReadFiles) {
        static int pcapFilePos = 0;

        fullfilename = config.pcapReadFiles[pcapFilePos];

        if (!fullfilename) {
            goto filesDone;
        }
        pcapFilePos++;

        if (reader_libpcapfile_process(fullfilename)) {
            return reader_libpcapfile_next();
        }

        return 1;
    }

filesDone:
    if (config.pcapFileLists) {
        static int pcapFileListsPos;
        static FILE *file;
        char line[PATH_MAX];

        if (!file && !config.pcapFileLists[pcapFileListsPos]) {
            goto fileListsDone;
        }

        if (!file) {
            if (strcmp(config.pcapFileLists[pcapFileListsPos], "-") == 0)
                file = stdin;
            else
                file = fopen(config.pcapFileLists[pcapFileListsPos], "r");
            pcapFileListsPos++;
            if (!file) {
                LOG("ERROR - Couldn't open %s", config.pcapFileLists[pcapFileListsPos - 1]);
                return reader_libpcapfile_next();
            }
        }

        if (feof(file)) {
            fclose(file);
            file = NULL;
            return reader_libpcapfile_next();
        }

        if (!fgets(line, sizeof(line), file)) {
            fclose(file);
            file = NULL;
            return reader_libpcapfile_next();
        }

        int lineLen = strlen(line);
        if (line[lineLen-1] == '\n') {
            line[lineLen-1] = 0;
        }

        g_strstrip(line);
        if (!line[0] || line[0] == '#')
            return reader_libpcapfile_next();

        if (reader_libpcapfile_process(line)) {
            return reader_libpcapfile_next();
        }

        return 1;
    }


fileListsDone:
    if (config.pcapReadDirs) {
        static int   pcapDirPos = 0;
        static GDir *pcapGDir[21];
        static char *pcapBase[21];
        static int   pcapGDirLevel = -1;
        GError      *error = 0;

        if (pcapGDirLevel == -2) {
            goto dirsDone;
        }

        if (pcapGDirLevel == -1) {
            pcapGDirLevel = 0;
            pcapBase[0] = config.pcapReadDirs[pcapDirPos];
            if (!pcapBase[0]) {
                pcapGDirLevel = -2;
                goto dirsDone;
            }
        }

        if (!pcapGDir[pcapGDirLevel]) {
            pcapGDir[pcapGDirLevel] = g_dir_open(pcapBase[pcapGDirLevel], 0, &error);
            if (error) {
                LOGEXIT("ERROR: Couldn't open pcap directory: Receive Error: %s", error->message);
            }
        }
        while (1) {
            const gchar *filename = g_dir_read_name(pcapGDir[pcapGDirLevel]);

            // No more files, stop processing this directory
            if (!filename) {
                break;
            }

            // Skip hidden files/directories
            if (filename[0] == '.')
                continue;

            fullfilename = g_build_filename (pcapBase[pcapGDirLevel], filename, NULL);

            // If recursive option and a directory then process all the files in that dir
            if (config.pcapRecursive && g_file_test(fullfilename, G_FILE_TEST_IS_DIR)) {
                if (pcapGDirLevel >= 20)
                    continue;
                pcapBase[pcapGDirLevel+1] = fullfilename;
                pcapGDirLevel++;
                return reader_libpcapfile_next();
            }

            if (!g_regex_match(config.offlineRegex, filename, 0, NULL)) {
                g_free(fullfilename);
                continue;
            }

            if (reader_libpcapfile_process(fullfilename)) {
                g_free(fullfilename);
                continue;
            }

            g_free(fullfilename);
            return 1;
        }
        g_dir_close(pcapGDir[pcapGDirLevel]);
        pcapGDir[pcapGDirLevel] = 0;

        if (pcapGDirLevel > 0) {
            g_free(pcapBase[pcapGDirLevel]);
            pcapGDirLevel--;
            return reader_libpcapfile_next();
        } else {
            pcapDirPos++;
            pcapGDirLevel = -1;
            return reader_libpcapfile_next();
        }

    }

dirsDone:
    while (DLL_COUNT(s_, &monitorQ) > 0) {
        MolochString_t *string;
        DLL_POP_HEAD(s_, &monitorQ, string);
        fullfilename = string->str;
        MOLOCH_TYPE_FREE(MolochString_t, string);

        if (reader_libpcapfile_process(fullfilename)) {
            g_free(fullfilename);
            continue;
        }

        g_free(fullfilename);
        return 1;
    }
    return 0;
}
예제 #11
0
파일: http.c 프로젝트: ariosx/moloch
gboolean moloch_http_send(void *serverV, char *method, char *key, uint32_t key_len, char *data, uint32_t data_len, gboolean dropable, MolochResponse_cb func, gpointer uw)
{
    MolochRequest_t     *request;
    MolochConn_t        *conn;
    MolochHttp_t        *server = serverV;

    request = MOLOCH_TYPE_ALLOC(MolochRequest_t);
    memcpy(request->key, key, MIN(key_len, sizeof(request->key)));
    strncpy(request->method, method, sizeof(request->method));
    request->key_len  = key_len;
    request->compress = 0;

    if (server->compress && data && data_len > 1000) {
        char            *buf = moloch_http_get_buffer(data_len);
        int              ret;

        z_strm.avail_in   = data_len;
        z_strm.next_in    = (unsigned char *)data;
        z_strm.avail_out  = data_len;
        z_strm.next_out   = (unsigned char *)buf;
        ret = deflate(&z_strm, Z_FINISH);
        if (ret == Z_STREAM_END) {
            request->compress = 1;
            MOLOCH_SIZE_FREE(buffer, data);
            data_len = data_len - z_strm.avail_out;
            data     = buf;
        } else {
            MOLOCH_SIZE_FREE(buffer, buf);
        }

        deflateReset(&z_strm);
    }

    request->data_len = data_len;
    request->data     = data;
    request->func     = func;
    request->uw       = uw;

    int q = data_len > MOLOCH_HTTP_BUFFER_SIZE?1:0;

    // Already have outstanding requests, see if we can process them
    if (server->requestQ[q].r_count && server->connQ.e_count && time(0) - server->lastFailedConnect > 0 ) {
        while (DLL_POP_HEAD(e_, &server->connQ, conn)) {
            DLL_POP_HEAD(r_, &server->requestQ[q], conn->request);
            if (conn->request) {
                if (!moloch_http_process_send(conn, 0)) {
                    LOG("ERROR - %p: Couldn't send %.*s", (void*)conn, conn->request->key_len, conn->request->key);
                    DLL_PUSH_HEAD(r_, &server->requestQ[q], conn->request);
                    conn->request = 0;
                    DLL_PUSH_TAIL(e_, &server->connQ, conn);
                    break;
                }
            }
            else {
                DLL_PUSH_TAIL(e_, &server->connQ, conn);
                break;
            }
        }
    }

    // Now see if we can send something new
    if (DLL_POP_HEAD(e_, &server->connQ, conn)) {
        conn->request = request;
        if (!moloch_http_process_send(conn, FALSE)) {
            conn->request = 0;
            DLL_PUSH_TAIL(r_, &server->requestQ[q], request);
            DLL_PUSH_TAIL(e_, &server->connQ, conn);
        }
    } else {
        request->data = data;
        if (!config.exiting && dropable && server->requestQ[q].r_count > server->maxOutstandingRequests) {
            LOG("ERROR - Dropping request %.*s of size %d queue[%d] %d is too big", key_len, key, data_len, q, server->requestQ[q].r_count);

            if (data) {
                MOLOCH_SIZE_FREE(buffer, data);
            }
            MOLOCH_TYPE_FREE(MolochRequest_t, request);
            return 1;
        } else {
            DLL_PUSH_TAIL(r_, &server->requestQ[q], request);
        }
    }

    return 0;
}
예제 #12
0
파일: http.c 프로젝트: ariosx/moloch
gboolean moloch_http_read_cb(gint UNUSED(fd), GIOCondition cond, gpointer data) {
    MolochConn_t        *conn = data;
    char                 buffer[0xffff];
    int                  len;
    GError              *gerror = 0;

    len = g_socket_receive(conn->conn, buffer, sizeof(buffer)-1, NULL, &gerror);

    if (gerror || cond & (G_IO_HUP | G_IO_ERR) || len <= 0) {
        if (gerror) {
            LOG("ERROR: %p:%p Receive Error: %s", (void*)conn, conn->request, gerror->message);
            g_error_free(gerror);
        } else if (cond & (G_IO_HUP | G_IO_ERR))
            LOG("ERROR: %p:%p Lost connection to %s", (void*)conn, conn->request, conn->name);
        else if (len <= 0)
            LOG("ERROR: %p:%p len: %d cond: %x", (void*)conn, conn->request, len, cond);
        else
            LOG("ERROR HMM: %p:%p len: %d cond: %x", (void*)conn, conn->request, len, cond);

        if (conn->request) {
            // Must save, free, then call function because of recursive sync GETs
            MolochResponse_cb  func = conn->request->func;
            gpointer           uw = conn->request->uw;

            MOLOCH_TYPE_FREE(MolochRequest_t, conn->request);

            if (func) {
                func(0, 0, uw);
            }
        }

        g_object_unref (conn->conn);
        conn->conn = 0;
        if (conn != conn->server->syncConn && conn->request) {
            DLL_PUSH_TAIL(e_, &conn->server->connQ, conn);
        }
        conn->request = 0;
        return FALSE;
    }

    http_parser_execute(&conn->parser, &parserSettings, buffer, len);

    if (conn->hp_complete) {
        gettimeofday(&conn->endTime, NULL);
        if (config.logESRequests)
            LOG("%s %ldms %ldms %ldms",
               conn->line,
               (conn->sendTime.tv_sec - conn->startTime.tv_sec)*1000 + (conn->sendTime.tv_usec - conn->startTime.tv_usec)/1000,
               (conn->sentTime.tv_sec - conn->startTime.tv_sec)*1000 + (conn->sentTime.tv_usec - conn->startTime.tv_usec)/1000,
               (conn->endTime.tv_sec - conn->startTime.tv_sec)*1000 + (conn->endTime.tv_usec - conn->startTime.tv_usec)/1000
               );

        conn->hp_data[conn->hp_len] = 0;

        /* Must save, free, then call function because of recursive sync GETs */
        MolochResponse_cb  func = conn->request->func;
        gpointer           uw = conn->request->uw;

        MOLOCH_TYPE_FREE(MolochRequest_t, conn->request);
        conn->request = 0;

        if (func) {
            func((unsigned char*)conn->hp_data, conn->hp_len, uw);
        }


        if (conn == conn->server->syncConn)
            return TRUE;


        int q;
        for (q = 0; q < 2; q++) {
            DLL_POP_HEAD(r_, &conn->server->requestQ[q], conn->request);
            if (conn->request) {
                if (!moloch_http_process_send(conn, 0)) {
                    DLL_PUSH_HEAD(r_, &conn->server->requestQ[q], conn->request);
                    conn->request = 0;
                    DLL_PUSH_TAIL(e_, &conn->server->connQ, conn);
                }
                return TRUE;
            }
        }
        DLL_PUSH_TAIL(e_, &conn->server->connQ, conn);
    }

    return TRUE;
}
예제 #13
0
파일: session.c 프로젝트: pstray/moloch
void moloch_session_process_commands(int thread)
{
    // Commands
    MolochSesCmd_t *cmd = 0;
    int count;
    for (count = 0; count < 50; count++) {
        MOLOCH_LOCK(sessionCmds[thread].lock);
        DLL_POP_HEAD(cmd_, &sessionCmds[thread], cmd);
        MOLOCH_UNLOCK(sessionCmds[thread].lock);
        if (!cmd)
            break;

        switch (cmd->cmd) {
        case MOLOCH_SES_CMD_ADD_TAG:
            moloch_field_int_add((long)cmd->uw1, cmd->session, (long)cmd->uw2);
            moloch_session_decr_outstanding(cmd->session);
            break;
        case MOLOCH_SES_CMD_FUNC:
            cmd->func(cmd->session, cmd->uw1, cmd->uw2);
            break;
        default:
            LOG ("Unknown cmd %d", cmd->cmd);
        }
        MOLOCH_TYPE_FREE(MolochSesCmd_t, cmd);
    }

    // Closing Q
    for (count = 0; count < 10; count++) {
        MolochSession_t *session = DLL_PEEK_HEAD(q_, &closingQ[thread]);

        if (session && session->saveTime < (uint64_t)lastPacketSecs[thread]) {
            moloch_session_save(session);
        } else {
            break;
        }
    }

    // Sessions Idle Long Time
    int ses;
    for (ses = 0; ses < SESSION_MAX; ses++) {
        for (count = 0; count < 10; count++) {
            MolochSession_t *session = DLL_PEEK_HEAD(q_, &sessionsQ[thread][ses]);

            if (session && (DLL_COUNT(q_, &sessionsQ[thread][ses]) > (int)config.maxStreams ||
                            ((uint64_t)session->lastPacket.tv_sec + config.timeouts[ses] < (uint64_t)lastPacketSecs[thread]))) {

                moloch_session_save(session);
            } else {
                break;
            }
        }
    }

    // TCP Sessions Open Long Time
    for (count = 0; count < 50; count++) {
        MolochSession_t *session = DLL_PEEK_HEAD(tcp_, &tcpWriteQ[thread]);

        if (session && (uint64_t)session->saveTime < (uint64_t)lastPacketSecs[thread]) {
            moloch_session_mid_save(session, lastPacketSecs[thread]);
        } else {
            break;
        }
    }
}