/**
 * This function initializes the tcp context global instance to 0 except for
 * file descriptor descriptor for stdin, stdout and stderr.
 *
 * @author    Mohd Naushad Ahmed
 * @version   1.0
 * @param     none
 * @return    none
 */
int tcp_process_request_cb ( int fd, int msg_type, char *data, int data_len )
{
  switch ((msg_req_type_t)msg_type)
  {
    case MSG_NEW_CONNECTION_REQ:
      (void) tcp_new_connection ( fd );
      break;
      
    case MSG_DATA_RECEIVED_REQ:
      (void) tcp_clr_read_fd ( fd );
      http_process_http_req ( fd, data, data_len );
      (void) tcp_set_write_fd ( fd );
      break;
      
    case MSG_CLOSE_CONNECTION_REQ:
      (void) tcp_close_connection ( fd );
      break;
      
    case MSG_DATA_SENT_REQ:
      (void) tcp_clr_write_fd ( fd );
      http_process_http_response ( fd, data, data_len );
      (void) tcp_set_read_fd ( fd );
      break;
    default:
      //log_dbg("NO CASE IS MATCHED");
      break;
  }
  return ( 0 );
}/* tcp_process_request_cb */
Beispiel #2
0
/**
 * Main loop. Handles the following:
 *   - Input from STDIN.
 *   - Messages from programs.
 *   - Packets from the socket.
 *   - Timeouts.
 */
void do_loop() {
  char buf[MAX_PACKET_SIZE];
  conn_t *conn = NULL;

  while (true) {
    memset(buf, 0, MAX_PACKET_SIZE);
    poll(events, NUM_POLL + num_connected,
         need_timer_in(&last_timeout, ctcp_cfg->timer));

    /* Input from stdin. Server will only send to most-recently connected
       client. */
    if (!run_program && events[STDIN_FILENO].revents & POLLIN) {
      conn = get_connections();

      if (conn != NULL)
        ctcp_read(conn->state);
    }

    /* See if we can output more. */
    if (events[STDOUT_FILENO].revents & (POLLOUT | POLLHUP | POLLERR)) {
      for (conn = get_connections(); conn; conn = conn->next) {
        conn_drain(conn);
      }
    }

    /* Poll for output received from running programs. Send to client
       client associated with this program instance. */
    if (run_program) {
      conn = get_connections();
      while (conn != NULL) {
        if (conn->poll_fd->revents & POLLIN) {
          ctcp_read(conn->state);
        }
        conn = conn->next;
      }
    }

    /* Receive packet on socket from other hosts. Ignore packets if they are
       not large enough or not for us. */
    if (events[2].revents & POLLIN) {
      conn = NULL;
      int len = recv_filter(config->socket, buf, MAX_PACKET_SIZE, 0, &conn);
      if (len >= FULL_HDR_SIZE) {
        tcphdr_t *tcp_hdr = (tcphdr_t *) (buf + IP_HDR_SIZE);

        /* Packet from an established connection. Pass to student code. */
        if (conn != NULL) {
          ctcp_segment_t *segment = convert_to_ctcp(conn, buf, len);
          len = len - FULL_HDR_SIZE + sizeof(ctcp_segment_t);

          /* Don't log or forward to student code if it's an ACK from a new
             connection. */
          if (tcp_hdr->th_sport == new_connection &&
              (segment->flags & TH_ACK) &&
              ntohl(segment->seqno) == 1 && ntohl(segment->ackno) == 1) {
            new_connection = 0;
            free(segment);
          }
          else {
            if (log_file != -1 || test_debug_on) {
              log_segment(log_file, config->ip_addr, config->port, conn,
                          segment, len, false, unix_socket);
            }
            ctcp_receive(conn->state, segment, len);
          }
        }

        /* New connection. */
        else if (tcp_hdr->th_flags & TH_SYN) {
          conn_t *conn = tcp_new_connection(buf);

          /* Start a new program associated with this client. */
          if (run_program && conn)
            execute_program(conn);
          new_connection = tcp_hdr->th_sport;
        }
      }
    }

    /* Check if timer is up. */
    if (need_timer_in(&last_timeout, ctcp_cfg->timer) == 0) {
      ctcp_timer();
      get_time(&last_timeout);
    }

    /* Delete connections if needed. */
    delete_all_connections();
  }
}