Ejemplo n.º 1
0
int chitcpd_tcp_state_handle_SYN_SENT(serverinfo_t *si, chisocketentry_t *entry, tcp_event_type_t event){
  tcp_data_t *data = &entry->socket_state.active.tcp_data;
  if (event == PACKET_ARRIVAL){
    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);
      /* This condition checks if there is an ack that it is acceptable and there is a syn*/
      if (((head->ack && ((data->SND_UNA <= SEG_ACK(pack)) && (SEG_ACK(pack) <= data->SND_NXT))) || !head->ack) && head->syn){
	
	data->RCV_NXT = SEG_SEQ(pack)+1;
	data->IRS = SEG_SEQ(pack);
	
	if (head->ack){ //only if its an ack
	  data->SND_WND = SEG_WND(pack);
	  data->SND_UNA = SEG_ACK(pack);
	}

	if (data->SND_UNA > data->ISS){
	  send_ACK(si, entry, data);

	  data->SND_UNA = data->SND_NXT;

	  chitcpd_update_tcp_state(si,entry,ESTABLISHED);
 
	  chitcp_tcp_packet_free(pack);
	  return CHITCP_OK;
	} else {
	  tcp_packet_t *new_pack = (tcp_packet_t*)malloc(sizeof(tcp_packet_t));
	  chitcpd_tcp_packet_create(entry,new_pack,NULL,0);
	  tcphdr_t *SYN_ACK = TCP_PACKET_HEADER(new_pack);
	  
	  SYN_ACK->seq = chitcp_htonl(data->ISS);
	  SYN_ACK->ack_seq = chitcp_htonl(data->RCV_NXT);
	  SYN_ACK->syn = 1;
	  SYN_ACK->ack = 1;
	  SYN_ACK->win = chitcp_htons(data->RCV_WND);

	  chilog_tcp(CRITICAL,new_pack,LOG_OUTBOUND);
	  chitcpd_send_tcp_packet(si,entry,new_pack);
	  chitcpd_update_tcp_state(si,entry,SYN_RCVD);
 
	  chitcp_tcp_packet_free(pack);
	  chitcp_tcp_packet_free(new_pack);
	  return CHITCP_OK;
	}
      }
    } else
    chilog(WARNING, "In SYN_SENT state, received unexpected event.");
 
  return CHITCP_OK;
}
Ejemplo n.º 2
0
int chitcpd_tcp_state_handle_CLOSING(serverinfo_t *si, chisocketentry_t *entry, tcp_event_type_t event) {
  tcp_data_t *data = &entry->socket_state.active.tcp_data;
  if (event == PACKET_ARRIVAL) {
    while (!list_empty(&data->pending_packets)) {
      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->ack) { 
	if (inside_window(data, pack)) {
	  update_WND_and_UNA(data, pack);
	  chitcpd_update_tcp_state(si, entry, TIME_WAIT);
     
	}

	if (head->fin)
	  always_on_fb(si, entry, data, pack);
      }
      chitcp_tcp_packet_free(pack);
    }
  } else
    chilog(WARNING, "In CLOSING state, received unexpected event (%i).", event);

  return CHITCP_OK;
}
Ejemplo n.º 3
0
int chitcpd_tcp_state_handle_SYN_RCVD(serverinfo_t *si, chisocketentry_t *entry, tcp_event_type_t event){
  tcp_data_t *data = &entry->socket_state.active.tcp_data;
  if (event == PACKET_ARRIVAL){
    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)){
      //Its acceptable, but is this true in all cases or just receiving information

      if (head->ack && ((data->SND_UNA <= SEG_ACK(pack)) && (SEG_ACK(pack) <= data->SND_NXT))){
	data->SND_UNA = data->SND_NXT;
	data->SND_WND = SEG_WND(pack);
	
	chitcpd_update_tcp_state(si,entry,ESTABLISHED);
      } else {
	send_ACK(si, entry, data);
	data->SND_WND = SEG_WND(pack);
      }
    }
    chitcp_tcp_packet_free(pack);
  } else
    chilog(WARNING, "In SYN_RCVD state, received unexpected event.");
 
  return CHITCP_OK;
}
Ejemplo n.º 4
0
int chitcpd_tcp_state_handle_CLOSE_WAIT(serverinfo_t *si, chisocketentry_t *entry, tcp_event_type_t event) {
  tcp_data_t *data = &entry->socket_state.active.tcp_data;
  if (event == APPLICATION_CLOSE) {
   
    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);

    send_all(si, entry, data);

    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,LAST_ACK);
    
    chitcp_tcp_packet_free(new_pack);
  } else if (event == PACKET_ARRIVAL) {
    while (!list_empty(&data->pending_packets)) {
     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->ack) { 
	if (inside_window(data, pack))
	  update_WND_and_UNA(data, pack);

	if (head->fin){
	  always_on_fb(si, entry, data, pack);
	 
	}
      }
      chitcp_tcp_packet_free(pack);
    }
  } else
    chilog(WARNING, "In CLOSE_WAIT state, received unexpected event (%i).", event);

  return CHITCP_OK;
}
Ejemplo n.º 5
0
int chitcpd_tcp_state_handle_LISTEN(serverinfo_t *si, chisocketentry_t *entry, tcp_event_type_t event){
  tcp_data_t *data = &entry->socket_state.active.tcp_data;

  if (event == PACKET_ARRIVAL) {
    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 (head->syn) {
      data->RCV_NXT = SEG_SEQ(pack) + 1;
      data->IRS = SEG_SEQ(pack);
      data->ISS = rand() % 1000 + 1;

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

      tcp_packet_t *new_pack = (tcp_packet_t*)malloc(sizeof(tcp_packet_t));
      chitcpd_tcp_packet_create(entry,new_pack,NULL,0);
      tcphdr_t *SYN_ACK = TCP_PACKET_HEADER(new_pack);

      SYN_ACK->seq = chitcp_htonl(data->ISS);
      SYN_ACK->ack_seq = chitcp_htonl(data->RCV_NXT);
      SYN_ACK->syn = 1;
      SYN_ACK->ack = 1;
      SYN_ACK->win = chitcp_htons(data->RCV_WND);
     
      chilog_tcp(CRITICAL,new_pack,LOG_OUTBOUND);  
      chitcpd_send_tcp_packet(si,entry,new_pack);

      data->SND_WND = SEG_WND(pack);

      data->SND_NXT = data->ISS + 1;
      data->SND_UNA = data->ISS;
      
      chitcpd_update_tcp_state(si,entry,SYN_RCVD);
     
      chitcp_tcp_packet_free(pack);
      chitcp_tcp_packet_free(new_pack);
      return CHITCP_OK;
    }
  } else
    chilog(WARNING, "In LISTEN state, received unexpected event.");
 
  return CHITCP_OK;
}
Ejemplo n.º 6
0
int chitcpd_tcp_state_handle_CLOSED(serverinfo_t *si, chisocketentry_t *entry, tcp_event_type_t event){
  tcp_data_t *data = &entry->socket_state.active.tcp_data;

  if (event == APPLICATION_CONNECT) { 
    /* Initializes the data */
   
    data->ISS = rand() % 1000 + 1;
    data->SND_UNA = data->ISS;
    data->SND_NXT = data->ISS + 1;
    
    data->RCV_WND = circular_buffer_available(&data->recv);
   
    tcp_packet_t *pack = (tcp_packet_t*)malloc(sizeof(tcp_packet_t));
    chitcpd_tcp_packet_create(entry,pack,NULL,0);
    tcphdr_t *SYN = TCP_PACKET_HEADER(pack);
 
    SYN->seq = chitcp_htonl(data->ISS);
    SYN->ack_seq = chitcp_htonl(data->ISS + 1);
    SYN->syn = 1;
    SYN->win = chitcp_htons(data->RCV_WND);
    
    chilog_tcp(CRITICAL,pack,LOG_OUTBOUND);  
    chitcpd_send_tcp_packet(si,entry,pack);
   
    chitcpd_update_tcp_state(si,entry,SYN_SENT);
    chitcp_tcp_packet_free(pack);
 

  } else if (event == CLEANUP) {
    chitcpd_free_socket_entry(si, entry);
    pthread_exit(NULL);
    /* Any additional cleanup goes here */
  } else
    chilog(WARNING, "In CLOSED state, received unexpected event.");
 
  return CHITCP_OK;
}
Ejemplo n.º 7
0
int chitcpd_tcp_state_handle_LAST_ACK(serverinfo_t *si, chisocketentry_t *entry, tcp_event_type_t event) {
  tcp_data_t *data = &entry->socket_state.active.tcp_data;
  if (event == PACKET_ARRIVAL) {

    while (!list_empty(&data->pending_packets)){
      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->ack) {
	if (inside_window(data, pack)) {
	  circular_buffer_free(&data->recv);
	  circular_buffer_free(&data->send);
	  list_destroy(&data->pending_packets);
	  pthread_mutex_destroy(&data->lock_pending_packets);
	  pthread_mutex_destroy(&data->lock_withheld_packets);
	  list_destroy(&data->withheld_packets);
	  free(data);
	  
	  chitcpd_update_tcp_state(si, entry, CLOSED);
	}
      }
      chitcp_tcp_packet_free(pack);
    }
  } else
    chilog(WARNING, "In LAST_ACK state, received unexpected event (%i).", event);

  return CHITCP_OK;
}
Ejemplo n.º 8
0
/*
 * chitcpd_handler_dispatch - Handler thread function
 *
 * Handles a connection on chitcpd's UNIX socket, and dispatches
 * incoming requests to the appropriate function, using the
 * dispatch table defined above.
 *
 * args: arguments (in handler_thread_args_t)
 *
 * Returns: Nothing.
 *
 */
void* chitcpd_handler_dispatch(void *args)
{
    handler_thread_args_t *ha = (handler_thread_args_t *) args;

    serverinfo_t *si = ha->si;
    socket_t client_socket = ha->client_socket;
    pthread_mutex_t *handler_lock = ha->handler_lock;
    pthread_setname_np(pthread_self(), ha->thread_name);
    ChitcpdMsg *req;
    ChitcpdMsg resp_outer = CHITCPD_MSG__INIT;
    ChitcpdResp resp_inner = CHITCPD_RESP__INIT;
    bool_t done = FALSE; /* Should we keep looping? */
    int rc;

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

    do
    {
        rc = chitcpd_recv_msg(client_socket, &req);
        if (rc < 0)
            break;

        chilog(TRACE, "Received request (code=%s)", handler_code_string(req->code));

        /* We have received a request, so we grab the handler lock to
         * prevent a race condition when the server is shutting down */
        pthread_mutex_lock(handler_lock);

        /* Call handler function using dispatch table */
        rc = handlers[req->code](si, req, &resp_inner);

        chitcpd_msg__free_unpacked(req, NULL);

        if(rc != CHITCP_OK)
        {
            chilog(ERROR, "Error when handling request.");
            /* We don't need to bail out just because one request failed */
        }

        /* Send response */
        rc = chitcpd_send_msg(client_socket, &resp_outer);

        if (resp_inner.has_buf)
        {
            /* This buffer was allocated in RECV. */
            free(resp_inner.buf.data);
            resp_inner.has_buf = FALSE;
        }
        if (resp_inner.socket_state != NULL)
        {
            /* This submessage was allocated in GET_SOCKET_STATE. */
            free(resp_inner.socket_state);
            resp_inner.socket_state = NULL;
        }
        if (resp_inner.socket_buffer_contents != NULL)
        {
            /* This submessage was allocated in GET_SOCKET_BUFFER_CONTENTS. */
            if (resp_inner.socket_buffer_contents->snd.data != NULL)
                free(resp_inner.socket_buffer_contents->snd.data);
            if (resp_inner.socket_buffer_contents->rcv.data != NULL)
                free(resp_inner.socket_buffer_contents->rcv.data);
            free(resp_inner.socket_buffer_contents);
            resp_inner.socket_buffer_contents = NULL;
        }

        /* We're done processing the request (we've run the handler and
         * we've returned a response). We can release the handler lock and,
         * if a shutdown is in progress, it will make sure it can proceed
         * safely */
        pthread_mutex_unlock(handler_lock);

        if (rc < 0)
            break;

    }
    while (!done);

    /* TODO: Be more discerning about what kind of shutdown this is */
    if(si->state == CHITCPD_STATE_STOPPING)
        chilog(DEBUG, "chiTCP daemon is stopping. Freeing open sockets for this handler...");
    else
        chilog(DEBUG, "Daemon client has disconnected. Freeing open sockets for this handler...");

    int freed_sockets = 0;

    for(int i=0; i < si->chisocket_table_size; i++)
    {
        chisocketentry_t *entry = &si->chisocket_table[i];
        if(!entry->available && entry->creator_thread == pthread_self())
        {
            chilog(DEBUG, "Freeing socket %i", i);
            /* TODO: The connection should be aborted (not closed) here.
             * However, we do not currently support the ABORT call or
             * RST's so we simply "force close" each socket. */

            if(entry->actpas_type == SOCKET_ACTIVE)
            {
                /* Any transition to CLOSED will force a termination of the TCP thread */
                chitcpd_update_tcp_state(si, entry, CLOSED);
                pthread_join(entry->socket_state.active.tcp_thread, NULL);
            }
            else if(entry->actpas_type == SOCKET_PASSIVE)
                chitcpd_free_socket_entry(si, entry);

            freed_sockets++;
            /* TODO: Close the connection */
        }
    }
    if (freed_sockets)
        chilog(DEBUG, "Done freeing open sockets.");
    else
        chilog(DEBUG, "This handler had no sockets to free.");

    chilog(DEBUG, "Handler is exiting.");
    free(args);
    return NULL;
}