Пример #1
0
int chitcpd_tcp_state_handle_ESTABLISHED(serverinfo_t *si, chisocketentry_t *entry, tcp_event_type_t event){
  tcp_data_t *data = &entry->socket_state.active.tcp_data;
  if (event == APPLICATION_SEND) {      
    send_all(si,entry,data);
  } else if (event == PACKET_ARRIVAL) {
    while (!list_empty(&data->pending_packets) && circular_buffer_available(&data->recv)){
      pthread_mutex_lock(&data->lock_pending_packets);
      tcp_packet_t *pack = list_fetch(&(data->pending_packets));
      pthread_mutex_unlock(&data->lock_pending_packets);
      tcphdr_t * head = TCP_PACKET_HEADER(pack);
    
      if (!acceptability_test(data, pack)) {
	send_ACK(si, entry, data);
	chitcp_tcp_packet_free(pack);
	return CHITCP_OK; 
      }
     
      if (!head->syn && head->ack) {
	if (inside_window(data, pack))
	  update_WND_and_UNA(data, pack);

	if (TCP_PAYLOAD_LEN(pack))
	  use_data(si, entry, data, pack);

	if (head->fin){
	  always_on_fb(si, entry, data, pack);  
	  chitcpd_update_tcp_state(si, entry, CLOSE_WAIT);
	}	
      }
      chitcp_tcp_packet_free(pack);
    }
  } else if (event == APPLICATION_RECEIVE){

    data->RCV_WND = circular_buffer_available(&data->recv); 
  

  } else if (event == APPLICATION_CLOSE){
    
    send_all(si,entry,data);
    
    tcp_packet_t *new_pack = (tcp_packet_t*)malloc(sizeof(tcp_packet_t));
    chitcpd_tcp_packet_create(entry,new_pack,NULL,0);
    tcphdr_t *FIN = TCP_PACKET_HEADER(new_pack);
	
    FIN->seq = chitcp_htonl(data->SND_NXT);
    FIN->ack_seq = chitcp_htonl(data->RCV_NXT);
    FIN->fin = 1;
    FIN->win = chitcp_htons(data->RCV_WND);

    chilog_tcp(CRITICAL,new_pack,LOG_OUTBOUND);
    chitcpd_send_tcp_packet(si,entry,new_pack);
    
    circular_buffer_close(&data->recv);
    circular_buffer_close(&data->send);
    
    chitcpd_update_tcp_state(si,entry,FIN_WAIT_1);

    chitcp_tcp_packet_free(new_pack);
  }
  else
    chilog(WARNING, "In ESTABLISHED state, received unexpected event (%i).", event);

  return CHITCP_OK;
}
Пример #2
0
/*
 * chitcpd_server_thread_func - Server thread function
 *
 * This function will spawn a handler thread (see handler.c) for each
 * new connection on the UNIX socket.
 *
 * args: arguments (a serverinfo_t variable in server_threads_args_t)
 *
 * Returns: Nothing.
 *
 */
void* chitcpd_server_thread_func(void *args)
{
    socklen_t sunSize;
    handler_thread_t *handler_thread;
    server_thread_args_t *sta;
    serverinfo_t *si;
    handler_thread_args_t *ha;
    list_t handler_thread_list;
    int rc;
    ChitcpdMsg *req;
    ChitcpdInitArgs *init_args;
    ChitcpdConnectionType conntype;
    ChitcpdMsg resp_outer = CHITCPD_MSG__INIT;
    ChitcpdResp resp_inner = CHITCPD_RESP__INIT;

    resp_outer.code = CHITCPD_MSG_CODE__RESP;
    resp_outer.resp = &resp_inner;

    /* For naming the handler threads we create (for debugging/logging) */
    int next_thread_id = 0;
    pthread_setname_np(pthread_self(), "unix_server");

    /* Unpack arguments */
    sta = (server_thread_args_t *) args;
    si = sta->si;

    list_init(&handler_thread_list);

    struct sockaddr_un client_addr;

    /* Accept connections on the UNIX socket */
    for(;;)
    {
        socket_t client_socket;

        /* Accept a connection */
        sunSize = sizeof(client_addr);
        if ((client_socket = accept(si->server_socket, (struct sockaddr *)&client_addr, &sunSize)) == -1)
        {
            /* If accept() returns in the CHITCPD_STATE_STOPPING, we don't
             * care what the error is. We just break out of the loop and
             * initiate an orderly shutdown. */
            if(si->state == CHITCPD_STATE_STOPPING)
                break;

            /* If this particular connection fails, no need to kill the entire thread. */
            perror("Could not accept() connection on UNIX socket");
            continue;
        }

        /* We receive a single message, which has to be an INIT message */
        rc = chitcpd_recv_msg(client_socket, &req);
        if (rc < 0)
        {
            if(si->state == CHITCPD_STATE_STOPPING)
                break;
            else
            {
                chilog(ERROR, "Error when receiving lead message through UNIX socket");
                shutdown(client_socket, SHUT_RDWR);
                continue;
            }
        }

        if(req->code != CHITCPD_MSG_CODE__INIT)
        {
            chilog(ERROR, "Expected INIT message, instead got message code %i", req->code);
            chitcpd_msg__free_unpacked(req, NULL);
            shutdown(client_socket, SHUT_RDWR);
            continue;
        }

        /* Unpack INIT request */
        assert(req->init_args != NULL);
        init_args = req->init_args;

        conntype = init_args->connection_type;


        /* There are two types of connections: command connections and debug
         * connections.
         *
         * When a command connection is created, a new thread is created to
         * handle the incoming chisocket commands on that connection (socket,
         * send, recv, etc.)
         *
         * When a debug connection is created, no additional thread is necessary.
         * The connection on the UNIX socket is simply "handed off" to a
         * debug monitor that will be associated with a chiTCP socket.
         * That UNIX socket is then used to send back debug messages.
         */

        if (conntype == CHITCPD_CONNECTION_TYPE__COMMAND_CONNECTION)
        {
            /* Create arguments for handler thread */
            ha = malloc(sizeof(handler_thread_args_t));
            ha->si = si;

            handler_thread = malloc(sizeof(handler_thread_t));
            handler_thread->handler_socket = client_socket;
            pthread_mutex_init(&handler_thread->handler_lock, NULL);

            /* Create handler thread to handle this connection */
            ha->client_socket = handler_thread->handler_socket;
            ha->handler_lock = &handler_thread->handler_lock;
            snprintf(ha->thread_name, 16, "socket-layer-%d", next_thread_id++);
            if (pthread_create(&handler_thread->thread, NULL, chitcpd_handler_dispatch, ha) != 0)
            {
                perror("Could not create a worker thread");

                resp_outer.resp->ret = CHITCP_ETHREAD;
                resp_outer.resp->error_code = 0;
                rc = chitcpd_send_msg(client_socket, &resp_outer);

                free(ha);
                close(ha->client_socket);
                close(si->server_socket);
                // TODO: Perform an orderly shutdown instead of exiting
                pthread_exit(NULL);
            }
            resp_outer.resp->ret = CHITCP_OK;
            resp_outer.resp->error_code = 0;
            rc = chitcpd_send_msg(client_socket, &resp_outer);

            list_append(&handler_thread_list, handler_thread);
        }
        else if(conntype == CHITCPD_CONNECTION_TYPE__DEBUG_CONNECTION)
        {
            int debug_sockfd, debug_event_flags;
            ChitcpdDebugArgs *debug_args;

            /* Unpack debug parameter */
            assert(init_args->debug != NULL);
            debug_args = init_args->debug;

            debug_sockfd = debug_args->sockfd;
            debug_event_flags = debug_args->event_flags;

            rc = chitcpd_init_debug_connection(si, debug_sockfd, debug_event_flags, client_socket);
            if(rc == CHITCP_OK)
            {
                resp_outer.resp->ret = CHITCP_OK;
                resp_outer.resp->error_code = 0;
                rc = chitcpd_send_msg(client_socket, &resp_outer);
            }
            else
            {
                chilog(ERROR, "Error when creating debug connection for socket %i", debug_sockfd);
                resp_outer.resp->ret = CHITCP_EINIT;
                resp_outer.resp->error_code = rc;
                rc = chitcpd_send_msg(client_socket, &resp_outer);

                shutdown(client_socket, SHUT_RDWR);
            }
        }
        else
        {
            chilog(ERROR, "Received INIT message with unknown connection type %i", conntype);
            resp_outer.resp->ret = CHITCP_EINVAL;
            resp_outer.resp->error_code = 0;
            rc = chitcpd_send_msg(client_socket, &resp_outer);
            shutdown(client_socket, SHUT_RDWR);
        }

        chitcpd_msg__free_unpacked(req, NULL);
    }

    while(!list_empty(&handler_thread_list))
    {
        /* For each handler thread we spawned, we close its socket, which
         * will force the thread to exit (and we then join it).
         *
         * Note that closing a handler thread will also free up all chiTCP
         * sockets created through that thread, and will also terminate
         * all associated TCP threads.
         *
         * TODO: We should simply detach those threads, since they can exit
         * before an orderly shutdown and would be left lingering until
         * we call join here. */
        handler_thread_t *ht = list_fetch(&handler_thread_list);

        /* We don't want to shutdown the handler's socket if an operation is
         * in progress. The handler thread may have read a command, but
         * not sent a response back yet */
        pthread_mutex_lock(&ht->handler_lock);
        shutdown(ht->handler_socket, SHUT_RDWR);
        pthread_mutex_unlock(&ht->handler_lock);
        pthread_join(ht->thread, NULL);
        pthread_mutex_destroy(&ht->handler_lock);
        free(ht);
    }

    list_destroy(&handler_thread_list);

    chilog(DEBUG, "Server thread is exiting.");

    pthread_exit(NULL);
}
Пример #3
0
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *   Update the csv context with the latest contents from the
 *   Falcon. For each buffer that has at least on hour worth of
 *   data, compress and write the data to the diskloop.
 */
void csv_poll( csv_context_t* csv_buffer_list, buffer_t* url_str,
               st_info_t* st_info, time_t initial_time )
{
    list_t* file_list = NULL;
    buffer_t* buf = NULL;
    buffer_t* url = NULL;
    char* file_name = NULL;
    const char* path = "/data/minute";
    csv_buffer_t csv_tmp;
    csv_buffer_t* csv_buffer;
    int location = 0;
    uint64_t file_hash = 0LL;

    uint8_t buffer_found = 0;

    int tally = 0;

    // Build the CSV directory URL
    url = buffer_init();
    buffer_write(url, url_str->content, url_str->length);
    buffer_write(url, (uint8_t*)path, strlen(path));
    buffer_terminate(url);

    // Initialize the CSV file list
    file_list = (list_t*)malloc(sizeof(list_t));
    if (!file_list)
        goto clean;
    list_init(file_list);
    list_attributes_seeker( file_list,  _file_list_seeker );
    list_attributes_comparator( file_list,  _file_list_comparator );

    // Get the html page listing the available CSV files
    buf = buffer_init();
    get_page((char*)url->content, buf);

    // Generate a list of files from the page
    if (!csv_get_file_list(file_list, buf))
        goto clean;
    buffer_reset(buf);
    buffer_reset(url);

    // Step through each CSV file and update its csv_buffer
    // in the csv_buffer_list
    while (!list_empty(file_list)) 
    {
        tally++;
        file_name = (char*)list_fetch(file_list);
        memset(&csv_tmp, 0, sizeof(csv_tmp));
        csv_tmp.file_name = file_name;

        // If there is not a csv buffer for this csv file, create a
        // new buffer and add it to the list
        if ((location = list_locate(csv_buffer_list, &csv_tmp)) < 0)
        {
            csv_buffer = csv_buffer_init();
            csv_buffer->file_name = file_name;
            list_append(csv_buffer_list, csv_buffer);
            buffer_found = 0;
        // Otherwise re-use the old csv buffer
        } else { 
            csv_buffer = (csv_buffer_t*)list_get_at(csv_buffer_list, location);
            buffer_found = 1;
        }

     // Process the contents of this CSV file
        // Generate the URL for retrieving the file
        buffer_write(url, url_str->content, url_str->length);
        buffer_write(url, (uint8_t*)csv_buffer->file_name,
                     strlen(csv_buffer->file_name));
        buffer_terminate(url);
        if (gDebug) {
            printf("getting page %s\n", url->content);
        }
        // Download the file
        get_page((char*)url->content, buf);
        file_hash = murmur_64_b( buf->content, buf->length, HASH_SEED_64 );
        if (gDebug) {
            fprintf(stderr, "file '%s' [0x%016llx] uncompressed size is %lu bytes\n",
                   csv_buffer->file_name, (unsigned long long)file_hash,
                   (unsigned long)buf->length);
            if (strcmp("/data/minute/logm1.csv", csv_buffer->file_name) == 0)
              fprintf(stderr, "'%s'\n", buf->content);
        }
        // Populate a csv_buffer with the contents of the file
        csv_parse_file(csv_buffer, buf, initial_time);
        if (gDebug) {
            fprintf(stderr, "The CSV buffer contains %u rows\n", csv_buffer->list->numels);
        }
        // Empty our temporary buffers
        buffer_reset(buf);
        buffer_reset(url);
        if (buffer_found) {
            free(file_name);
        }
        file_name = NULL;
        csv_buffer = NULL;
    }

// Clean up all temporary resources
clean:
    buf = buffer_destroy(buf);
    url = buffer_destroy(url);
    if (file_list) 
    {
        while(!list_empty(file_list))
        {
            file_name = list_fetch(file_list);
            if (file_name)
            {
                free(file_name);
            }
        }
        list_destroy(file_list);
        free(file_list);
    }
} // csv_poll()