Esempio n. 1
0
/* Listen for a connection from somebody else. When communication link is
 * created return a minisocket_t through which the communication can be made
 * from now on.
 *
 * The argument "port" is the port number on the local machine to which the
 * client will connect.
 *
 * Return value: the minisocket_t created, otherwise NULL with the errorcode
 * stored in the "error" variable.
 */
minisocket_t minisocket_server_create(int port, minisocket_error *error)
{
  minisocket_t new_sock;
  interrupt_level_t l;
  network_interrupt_arg_t * pkt;
  resend_arg* resend_alarm_arg;
  char tmp; 

  //check valid portnum
  if (port < 0 || port >= CLIENT_START){
    *error = SOCKET_INVALIDPARAMS;
    return NULL;
  }

  //check port in use
  semaphore_P(server_lock);

  //printf("calling server_create at port %d.\n", port);
  //printf("value at port %d is %li.\n", port, (long)sock_array[port]);
  if (sock_array[port] != NULL){
    *error = SOCKET_PORTINUSE;
    return NULL;
  }
  new_sock = (minisocket_t)malloc(sizeof(struct minisocket));
  if (!new_sock){
    semaphore_V(server_lock);
    *error = SOCKET_OUTOFMEMORY;
    return NULL;
  }
  new_sock->pkt_ready_sem = semaphore_create();
  if (!(new_sock->pkt_ready_sem)){
    semaphore_V(server_lock);
    free(new_sock);
    *error = SOCKET_OUTOFMEMORY;
    return NULL;
  }
  new_sock->pkt_q = queue_new();
  if (!(new_sock->pkt_q)){
    semaphore_V(server_lock);
    semaphore_destroy(new_sock->pkt_ready_sem);
    free(new_sock);
    *error = SOCKET_OUTOFMEMORY;
    return NULL;
  }
  new_sock->sock_lock = semaphore_create();
  if (!(new_sock->sock_lock)){
    semaphore_V(server_lock);
    free(new_sock->pkt_ready_sem);
    queue_free(new_sock->pkt_q);
    free(new_sock);
    *error = SOCKET_OUTOFMEMORY;
    return NULL;
  }
  new_sock->ack_ready_sem = semaphore_create();
  if (!(new_sock->ack_ready_sem)){
    semaphore_V(server_lock);
    semaphore_destroy(new_sock->pkt_ready_sem);
    queue_free(new_sock->pkt_q);
    semaphore_destroy(new_sock->sock_lock);
    free(new_sock);
    *error = SOCKET_OUTOFMEMORY;
    return NULL;
  }
  semaphore_initialize(new_sock->pkt_ready_sem, 0);
  semaphore_initialize(new_sock->ack_ready_sem, 0);
  semaphore_initialize(new_sock->sock_lock, 1);

  new_sock->curr_state = LISTEN;
  new_sock->try_count = 0;
  new_sock->curr_ack = 0;
  new_sock->curr_seq = 1;
  new_sock->resend_alarm = NULL; // no alarm set
  new_sock->src_port = port;
  new_sock->dst_port = -1; // not paired with client
  network_address_blankify(new_sock->dst_addr); // not paired with client

  sock_array[port] = new_sock;
  semaphore_V(server_lock);
 
  resend_alarm_arg = (resend_arg*)calloc(1, sizeof(resend_arg));
  while (1) {
    // wait for MSG_SYN
    semaphore_P(new_sock->ack_ready_sem);
    l = set_interrupt_level(DISABLED);
 
    switch (new_sock->curr_state) {
    case CONNECTING:  
      minisocket_send_ctrl(MSG_SYNACK, new_sock, error);

      resend_alarm_arg->sock = new_sock;
      resend_alarm_arg->msg_type = MSG_SYNACK;
      resend_alarm_arg->data_len = 0;
      resend_alarm_arg->data = &tmp; //placeholder
      resend_alarm_arg->error = error; 
      new_sock->resend_alarm = set_alarm(RESEND_TIME_UNIT, minisocket_resend, resend_alarm_arg, minithread_time());
      
      new_sock->curr_state = MSG_WAIT;
      set_interrupt_level(l);
      break;

    case CONNECTED:
      // must have gotten a MSG_ACK 
      //printf("in server_create, SUCCESS!\n");
      new_sock->try_count = 0;
      deregister_alarm(new_sock->resend_alarm);
      new_sock->resend_alarm = NULL;
      *error = SOCKET_NOERROR;
      set_interrupt_level(l);
      //printf("exiting server_create\n");
      free(resend_alarm_arg);
      return new_sock;
      break;

    case EXIT: default:
      *error = SOCKET_SENDERROR;
      // clean out the queue
      while (queue_dequeue(new_sock->pkt_q,(void**)&pkt) != -1){
        free(pkt);
      }
      new_sock->curr_state = LISTEN;
      new_sock->curr_ack = 0;
      new_sock->curr_seq = 1;
      set_interrupt_level(l);
      break;
    }
  }
  free(resend_alarm_arg);
  return new_sock;
}
Esempio n. 2
0
/* 
 * Listen for a connection from somebody else. When communication link is
 * created return a minisocket_t through which the communication can be made
 * from now on.
 *
 * The argument "port" is the port number on the local machine to which the
 * client will connect.
 *
 * Return value: the minisocket_t created, otherwise NULL with the errorcode
 * stored in the "error" variable.
 */
minisocket_t minisocket_server_create(int port, minisocket_error *error)
{
	minisocket_t newMinisocket;
	int ack_check;
	int connected = 1;
	network_interrupt_arg_t *arg;
	mini_header_reliable_t header;

	if (error == NULL)
		return NULL;

	if (port < TCP_MINIMUM_SERVER || port > TCP_MAXIMUM_SERVER)
	{
		*error = SOCKET_INVALIDPARAMS;
		return NULL;
	}

	semaphore_P(server_mutex);

	//Checks if port already exists
	if (minisockets[port] != NULL)
	{
		*error = SOCKET_PORTINUSE;
		semaphore_V(server_mutex);
		return NULL;
	}

	newMinisocket = minisocket_create_socket(port);
	if (newMinisocket == NULL)
	{
		*error = SOCKET_OUTOFMEMORY;
		semaphore_V(server_mutex);
		return NULL;
	}

	newMinisocket->port_type = TCP_PORT_TYPE_SERVER;
	minisockets[port] = newMinisocket;

	semaphore_V(server_mutex);

	while (connected == 1)
	{
		semaphore_P(newMinisocket->packet_ready);
		
		queue_dequeue(newMinisocket->waiting_packets, (void **) &arg);
		header = (mini_header_reliable_t) arg->buffer;
		if (header->message_type != MSG_SYN)
			continue;

		newMinisocket->status = TCP_PORT_CONNECTING;

		unpack_address(header->source_address, newMinisocket->destination_addr);
		newMinisocket->destination_port = unpack_unsigned_short(header->source_port);
		ack_check = transmit_packet(newMinisocket, newMinisocket->destination_addr, 
				newMinisocket->destination_port, 1, MSG_SYNACK, 0, NULL, error);

		if (ack_check == -1)
		{
			newMinisocket->status = TCP_PORT_LISTENING;
			network_address_blankify(newMinisocket->destination_addr);
			newMinisocket->destination_port = 0;
		}	
		else
		{
			newMinisocket->status = TCP_PORT_CONNECTED;
			connected = 0;
		}
	}

	*error = SOCKET_NOERROR;
	return newMinisocket;
}
Esempio n. 3
0
/* 
 * Listen for a connection from somebody else. When communication link is
 * created return a minisocket_t through which the communication can be made
 * from now on.
 *
 * The argument "port" is the port number on the local machine to which the
 * client will connect.
 *
 * Return value: the minisocket_t created, otherwise NULL with the errorcode
 * stored in the "error" variable.
 */
minisocket_t minisocket_server_create(int port, minisocket_error *error)
{
	minisocket_t minisocket;
	interrupt_level_t prev_level;
	int transmit_ret;
	int success = 0;

	if (error == NULL)
	{
		return NULL;
	}

	// Ensure the port is in the valid range
	if (port < TCP_MIN_SERVER || port > TCP_MAX_SERVER)
	{
		*error = SOCKET_INVALIDPARAMS;
		return NULL;
	}

	// We need to synchronize access to the server port range of the minisockets
	// pool, as we don't want another thread to try to create a socket on this port
	// concurrently
	semaphore_P(server_sem);

	// Ensure the port doesn't exist
	if (minisockets[port] != NULL)
	{
		*error = SOCKET_PORTINUSE;
		semaphore_V(server_sem);
		return NULL;
	}

	// Try to setup the socket struct
	minisocket = minisocket_setup_socket(port);
	if (minisocket == NULL)
	{
		*error = SOCKET_OUTOFMEMORY;
		semaphore_V(server_sem);
		return NULL;		
	}

	// Set the port type
	minisocket->port_type = TCP_PORT_TYPE_SERVER;

	// Insert the minisocket into the array
	minisockets[port] = minisocket;

	// Ensure we don't have with the server semaphore, so other servers
	// can be made while we wait for a client
	semaphore_V(server_sem);

	// Continuously wait for a successful connection
	while (success == 0)
	{
		// Wait for a connection
		prev_level = set_interrupt_level(DISABLED);
		semaphore_P(minisocket->wait_for_ack_sem);
		set_interrupt_level(prev_level);

		// When we're awoken and have a client, set the status
		minisocket->status = TCP_PORT_CONNECTING;

		// And send the SYNACK sequence
		minisocket->ack_num++; // we're acknowledging the SYN, and also sending a packet that increments seq#
		transmit_ret = transmit_packet(minisocket, minisocket->dst_addr, minisocket->dst_port, 
						1, MSG_SYNACK, 0, NULL, error);	

		if (transmit_ret == -1)
		{
			// This means we didn't get ACKs back, so this is a bad connection
			// Reset some port details and continue waiting
			minisocket->status = TCP_PORT_LISTENING;
			network_address_blankify(minisocket->dst_addr);
			minisocket->dst_port = 0;
			minisocket->ack_num--;
			minisocket->seq_num--;
		}
		 else
		{
			// Established connection successfully
			minisocket->status = TCP_PORT_CONNECTED;
			success = 1;
		}
	}

	*error = SOCKET_NOERROR;
	
	return minisocket;
}