Пример #1
0
// Create a packed reliable header given the parameters
mini_header_reliable_t create_reliable_header(network_address_t src_addr_raw, 
		int src_port_raw, network_address_t dst_addr_raw, int dst_port_raw, 
		char message_type, unsigned int seq_num_raw, unsigned int ack_num_raw) 
{
	mini_header_reliable_t header = (mini_header_reliable_t) malloc(sizeof(struct mini_header_reliable));
	//Fields
	char src_port[2];
	char dst_port[2];
	char src_addr[8];
	char dst_addr[8];
	char seq_num[4];
	char ack_num[4];

	//Pack everything
	pack_unsigned_short(src_port, (unsigned short) src_port_raw);
	pack_unsigned_short(dst_port, (unsigned short) dst_port_raw);
	pack_address(src_addr, src_addr_raw);
	pack_address(dst_addr, dst_addr_raw);
	pack_unsigned_int(seq_num, seq_num_raw);
	pack_unsigned_int(ack_num, ack_num_raw);

	//Set header fields
	header->protocol = (char) PROTOCOL_MINISTREAM;
	header->message_type = message_type;
	memcpy(header->source_address, src_addr, 8);
	memcpy(header->destination_address, dst_addr, 8);
	memcpy(header->source_port, src_port, 2);
	memcpy(header->destination_port, dst_port, 2);
	memcpy(header->seq_number, seq_num, 4);
	memcpy(header->ack_number, ack_num, 4);

	return header;
}
Пример #2
0
static mini_header_reliable_t *create_control_header(int msg_type, unsigned int dest_port,
						    network_address_t dest_addr, unsigned int src_port,
						     unsigned int seq, unsigned int ack)
{
  mini_header_reliable_t *header = (mini_header_reliable_t *) malloc(sizeof(mini_header_reliable_t));
  if (!header) {
    return NULL;
  }
    
  header->protocol = PROTOCOL_MINISTREAM + '0';

  network_address_t local_addr;
  network_address_copy(local_host, local_addr);
  //network_get_my_address(local_addr);

  pack_address(header->source_address, local_addr);
  pack_unsigned_short(header->source_port, src_port);

  header->message_type = msg_type + '0';
  pack_address(header->destination_address, dest_addr);
  pack_unsigned_short(header->destination_port, dest_port);
  pack_unsigned_int(header->seq_number, seq); 
  pack_unsigned_int(header->ack_number, ack); 
  return header;
}
Пример #3
0
/*
 * Pack header using the local receiving and sending ports.
 * Called by minimsg_sent.
 */
static void
minimsg_packhdr(mini_header_t hdr, miniport_t unbound, miniport_t bound)
{
    hdr->protocol = PROTOCOL_MINIDATAGRAM;
    pack_address(hdr->source_address, hostaddr);
    pack_unsigned_short(hdr->source_port, unbound->num);
    pack_address(hdr->destination_address, bound->bound.addr);
    pack_unsigned_short(hdr->destination_port, bound->bound.remote);
}
Пример #4
0
int transmit_first(int* arg)
{
    char buffer[MINIMSG_MAX_MSG_SIZE + 10];
    int length = 0;
    int i;
    network_address_t hostaddr, targetaddr;
    miniport_t port;
    miniport_t dest;
    struct mini_header hdr;

    AbortOnCondition(network_translate_hostname(hostname, targetaddr) < 0,
                     "Could not resolve hostname, exiting.");

    port = miniport_create_unbound(0);
    dest = miniport_create_bound(targetaddr, 1);

    /* Form correct header */
    network_get_my_address(hostaddr);
    hdr.protocol = PROTOCOL_MINIDATAGRAM;
    pack_address(hdr.source_address, hostaddr);
    pack_unsigned_short(hdr.source_port, port->num);
    pack_address(hdr.destination_address, dest->bound.addr);
    pack_unsigned_short(hdr.destination_port, dest->bound.remote);

    /* Send packages with short but correct header and zero data */
    printf("Sending packages with short headers.\n");
    sprintf(buffer, "Receiving packages with short headers.\n");
    length = strlen(buffer) + 1;
    minimsg_send(port, dest, buffer, length);

    for (i = 0; i < MINIMSG_HDRSIZE; i++)
        network_send_pkt(targetaddr, i, (char*)&hdr, 0, buffer);

    /* Send packages to wrong ports */
    printf("Sending packages to wrong destination ports.\n");
    sprintf(buffer, "Receiving packages with wrong destination ports.\n");
    length = strlen(buffer) + 1;
    minimsg_send(port, dest, buffer, length);
    sprintf(buffer, "This message is sent to a wrong port.\n");
    length = strlen(buffer) + 1;
    minimsg_send(port, miniport_create_bound(targetaddr, 0),
                 buffer, length);
    minimsg_send(port, miniport_create_bound(targetaddr, MAX_UNBOUNDED),
                 buffer, length);
    minimsg_send(port, miniport_create_bound(targetaddr, MAX_UNBOUNDED + 1),
                 buffer, length);
    minimsg_send(port, miniport_create_bound(targetaddr, MIN_BOUNDED),
                 buffer, length);
    minimsg_send(port, miniport_create_bound(targetaddr, MAX_BOUNDED),
                 buffer, length);

    printf("Send-first finished.\n");

    return 0;
}
Пример #5
0
/* Construct a (reliable) header to be sent by the given socket. */
void set_header(minisocket_t socket, mini_header_reliable_t hdr, char message_type) {
	network_address_t my_address;

	hdr->protocol = PROTOCOL_MINISTREAM; // Protocol
	network_get_my_address(my_address);
	pack_address(hdr->source_address, my_address); // Source address
	pack_unsigned_short(hdr->source_port, socket->local_port); // Source port
	pack_address(hdr->destination_address, socket->dest_address); // Destination address
	pack_unsigned_short(hdr->destination_port, socket->remote_port); // Destination port
	hdr->message_type = message_type; // Message type
	pack_unsigned_int(hdr->seq_number, socket->seqnum); // Sequence number
	pack_unsigned_int(hdr->ack_number, socket->acknum); // Acknowledgment number
}
Пример #6
0
/* minisocket_send_ctrl creates an ctrl packet of type type and with
 * fields taken from the sock parameter.
 * This ack packet is sent over the network.
 * If there is an underlying network failure, error is updated
 * but the pkt is not resent.
 * The address of pkt is given as the data buffer, 
 * but no data from pkt is written since the data_len is 0.
 */ 
void minisocket_send_ctrl(char type, minisocket_t sock, minisocket_error* error) {
  struct mini_header_reliable pkt;
  pkt.protocol = PROTOCOL_MINISTREAM;
  pack_address(pkt.source_address, my_addr);
  pack_unsigned_short(pkt.source_port, sock->src_port);
  pack_address(pkt.destination_address, sock->dst_addr);
  pack_unsigned_short(pkt.destination_port, sock->dst_port);
  pkt.message_type = type;
  pack_unsigned_int(pkt.seq_number, sock->curr_seq);
  pack_unsigned_int(pkt.ack_number, sock->curr_ack);
  
  if (network_send_pkt(sock->dst_addr, sizeof(pkt), 
      (char*)&pkt, 0, (char*)&pkt) == -1) {
    *error = SOCKET_SENDERROR;
  }  
}
Пример #7
0
/* Sends a message through a locally bound port (the bound port already has an associated
 * receiver address so it is sufficient to just supply the bound port number). In order
 * for the remote system to correctly create a bound port for replies back to the sending
 * system, it needs to know the sender's listening port (specified by local_unbound_port).
 * The msg parameter is a pointer to a data payload that the user wishes to send and does not
 * include a network header; your implementation of minimsg_send must construct the header
 * before calling miniroute_send_pkt(). The return value of this function is the number of
 * data payload bytes sent not inclusive of the header.
 */
int minimsg_send(miniport_t local_unbound_port, miniport_t local_bound_port, minimsg_t msg, int len) {
	network_address_t dest, my_address;
	mini_header_t hdr;

	// semaphore_P(msgmutex);

	// Check for valid arguments
	if (local_unbound_port == NULL) {
		fprintf(stderr, "ERROR: minimsg_send() passed a NULL local_unbound_port miniport argument\n");
		semaphore_V(msgmutex);
		return -1;
	}
	if (local_bound_port == NULL) {
		fprintf(stderr, "ERROR: minimsg_send() passed a NULL local_bound_port miniport argument\n");
		semaphore_V(msgmutex);
		return -1;
	}

	// Allocate new header for packet
	hdr = malloc(sizeof(struct mini_header));
	if (hdr == NULL) {	// Could not allocate header
		fprintf(stderr, "ERROR: minimsg_send() failed to malloc new mini_header\n");
		semaphore_V(msgmutex);
		return -1;
	}

	// Assemble packet header
	hdr->protocol = PROTOCOL_MINIDATAGRAM; // Protocol
	network_get_my_address(my_address);
	pack_address(hdr->source_address, my_address); // Source address
	pack_unsigned_short(hdr->source_port, local_bound_port->port_num); // Source port
	network_address_copy(local_bound_port->u.bound.remote_address, dest);
	pack_address(hdr->destination_address, dest); // Destination address
	pack_unsigned_short(hdr->destination_port, local_bound_port->u.bound.remote_unbound_port); // Destination port

	// Call miniroute_send_pkt() from network.hdr
	if (network_send_pkt(dest, sizeof(struct mini_header), (char*) hdr, len, msg) < 0) {			// REMOVE THIS LINE
	// if (miniroute_send_pkt(dest, sizeof(struct mini_header), (char*) hdr, len, msg) < 0) {
		fprintf(stderr, "ERROR: minimsg_send() failed to successfully execute miniroute_send_pkt()\n");
		semaphore_V(msgmutex);
		return -1;
	}

	// semaphore_V(msgmutex);

    return 0;
}
Пример #8
0
//Returns a reliable mini header
//TODO: do seq_num and ack_num
void minisocket_create_reliable_header(mini_header_reliable_t* header, minisocket_t* socket, unsigned short dest_port, const network_address_t dest_address, char message_type) {
  header->protocol = PROTOCOL_MINISTREAM;

  //packs info
  pack_address(header->destination_address, dest_address);
  pack_unsigned_short(header->destination_port, dest_port);
  network_address_t my_address;
  network_get_my_address(my_address);
  pack_address(header->source_address, my_address);
  pack_unsigned_short(header->source_port, socket->local_port_number);

  //pack seq and ack numbers
  pack_unsigned_int(header->ack_number, socket->ack);
  pack_unsigned_int(header->seq_number, socket->seq);

  //set message type
  header->message_type = message_type;
}
Пример #9
0
/* Sends a message through a locally bound port (the bound port already has an associated
 * receiver address so it is sufficient to just supply the bound port number). In order
 * for the remote system to correctly create a bound port for replies back to the sending
 * system, it needs to know the sender's listening port (specified by local_unbound_port).
 * The msg parameter is a pointer to a data payload that the user wishes to send and does not
 * include a network header; your implementation of minimsg_send must construct the header
 * before calling network_send_pkt(). The return value of this function is the number of
 * data payload bytes sent not inclusive of the header. Returns -1 on error.
 * Fails if msg is too long. 
 */
int
minimsg_send(miniport_t local_unbound_port, miniport_t local_bound_port, minimsg_t msg, int len) {
  struct mini_header hdr;
  network_address_t dst_addr;
  
  if (len > MINIMSG_MAX_MSG_SIZE) {
    return -1;
  }

  if (local_unbound_port == NULL || 
      local_unbound_port->p_type != UNBOUND_PORT || 
      local_unbound_port->p_num >= BOUND_PORT_START ||
      miniport_array[local_unbound_port->p_num] != local_unbound_port) {
    return -1;
  }

  if (local_bound_port == NULL ||
      local_bound_port->p_type != BOUND_PORT ||
      local_bound_port->p_num < BOUND_PORT_START ||
      miniport_array[local_bound_port->p_num] != local_bound_port) {
    return -1;
  }


  network_address_copy(local_bound_port->u.bound.dest_addr, dst_addr); 
  hdr.protocol = PROTOCOL_MINIDATAGRAM;
  pack_address(hdr.source_address, my_addr);
  pack_unsigned_short(hdr.source_port, local_unbound_port->p_num);
  pack_address(hdr.destination_address, local_bound_port->u.bound.dest_addr);
  pack_unsigned_short(hdr.destination_port, local_bound_port->u.bound.dest_num);
  
  if (network_send_pkt(dst_addr, sizeof(hdr), (char*)&hdr, len, msg)) {
    return -1;
  }
  return len;
}
Пример #10
0
int
minimsg_send(miniport_t* local_unbound_port, miniport_t* local_bound_port, minimsg_t* msg, int len)
{
	assert(g_boundPortCounter >= 0); //sanity check to ensure minimsg_initialize() has been called first

	//validate input
	if (local_unbound_port == NULL || local_bound_port == NULL || msg == NULL || len < 0 || len > MINIMSG_MAX_MSG_SIZE) return -1;

	//generate the header
	mini_header_t header;
	header.protocol = PROTOCOL_MINIDATAGRAM; //set protocol type
	network_address_t my_address;
	network_get_my_address(my_address);
	pack_address(header.source_address, my_address);
	pack_unsigned_short(header.source_port, local_unbound_port->port_number);
	pack_address(header.destination_address, local_bound_port->bound_port.remote_addr);
	pack_unsigned_short(header.destination_port, local_bound_port->bound_port.remote_unbound_port);
	
	//send message now
	int sentBytes = network_send_pkt(local_bound_port->bound_port.remote_addr, sizeof(header), (char*)&header, len, msg);

	if (sentBytes == -1) return -1; //we failed to send our message
	else return sentBytes - sizeof(header); //else return size of our message not inclusive of header
}
Пример #11
0
minisocket_t* minisocket_server_create(int port, minisocket_error *error) {	
  //Check socket number first 
  if (valid_server_port(port) == 0) {
    *error = SOCKET_INVALIDPARAMS;
    return NULL;
  }				
  //check if socket is already in use
  if (mini_socket_data[port] != NULL) {
    *error = SOCKET_PORTINUSE; 
    return NULL;
  }
  minisocket_t* socket = (minisocket_t *) malloc(sizeof(minisocket_t));
  if (socket == NULL) {
    *error = SOCKET_OUTOFMEMORY;
    return NULL;
  }

  socket->state = LISTENING;
  socket->socket_type = SERVER_TYPE;
  socket->local_port_number = port;
  network_address_t my_address;
  network_get_my_address(my_address);
  network_address_copy(my_address, socket->local_address);
  socket->datagrams_ready = semaphore_create();
  semaphore_initialize(socket->datagrams_ready, 0);
  socket->ack_ready = semaphore_create();
  semaphore_initialize(socket->ack_ready, 0);
  socket->incoming_data = queue_new();
  socket->acknowledgements = queue_new();
  socket->seq = 0;
  socket->ack = 0;
  socket->next_read = 0;

  //add socket to global array
  mini_socket_data[socket->local_port_number] = socket;

  char connection_established = 0;
  mini_header_reliable_t header; 
  minisocket_create_reliable_header((mini_header_reliable_t *) &header, socket, socket->remote_port_number, socket->remote_address, MSG_SYNACK); 
  network_address_t dest;
  
  pack_unsigned_int(header.seq_number, socket->seq);
  pack_unsigned_int(header.ack_number, socket->ack); 

  //loop until a full connection is established
  while (connection_established == 0) {
    //sleep until initial MSG_SYN arrives from client
    char message_received = 0;
    while (message_received == 0) {
      //Waits until it receives a packet
      semaphore_P(socket->ack_ready);

      interrupt_level_t old_level = set_interrupt_level(DISABLED);
      network_interrupt_arg_t* interrupt_message = NULL;
      queue_dequeue(socket->acknowledgements, (void **) &interrupt_message);
      set_interrupt_level(old_level);

      //TODO: check more contents of message? change seq and ack values in response??}
      if (interrupt_message != NULL ) {
        mini_header_reliable_t* received_header = (mini_header_reliable_t *) interrupt_message->buffer; 
        unpack_address(received_header->source_address, dest);
        pack_address(header.destination_address, dest);
        pack_unsigned_short(header.destination_port, unpack_unsigned_short(received_header->source_port));

        if (valid_client_port(unpack_unsigned_short(received_header->source_port)) == 1) { //check valid port number
          if (received_header->message_type != MSG_SYN) { //check valid message type
            header.message_type = MSG_FIN; 
            network_send_pkt(dest, sizeof(mini_header_reliable_t), (char *) &header, 0, empty_message); 
            free(interrupt_message); 
          }
          else {
            //set remote port values
            printf("server got the SYN message\n");
            socket->remote_port_number = unpack_unsigned_short(received_header->source_port);
            network_address_copy(dest, socket->remote_address);
            socket->seq = unpack_unsigned_int(received_header->seq_number);
            message_received = 1; //will break loop
            free(interrupt_message); 
            socket->state = CONNECTING;
            break;
          }
        }  
      }
    }
    //reset loop value for return
    message_received = 0;
    //otherwise the message was the correct type and format

    int timeout = START_TIMEOUT / 2; //this way first timeout will be at START_TIMEOUT
    for (int i = 0; i < MAX_FAILURES; i++) {
      printf("sending MSG_SYNACK in server, i: %d\n", i); 
      timeout = timeout * 2;
      header.message_type = MSG_SYNACK; 
      network_send_pkt(dest, sizeof(mini_header_reliable_t), (char *) &header, 0, empty_message); 
      alarm_id timeout_alarm_id = register_alarm(timeout, handshake_timeout_handler, (void *) socket->ack_ready);
      int alarm_fired = 0;

      //keep looking through received packets until either the alarm fires or it finds the correct packet
      while (!connection_established && !alarm_fired) {
        semaphore_P(socket->ack_ready);

        //alarm has fired, since there are no packets to be received
        if (queue_length(socket->acknowledgements) == 0) {
          alarm_fired = 1; //goes to next iteration of for loop
        }
        //There is a packet (alarm hasnt fired yet)
        else {
          network_interrupt_arg_t* interrupt_message = NULL;
          interrupt_level_t old_level = set_interrupt_level(DISABLED);
          queue_dequeue(socket->acknowledgements, (void **) &interrupt_message);
          set_interrupt_level(old_level); 

          // verify non null message
          if (interrupt_message != NULL) {
            mini_header_reliable_t* received_header = (mini_header_reliable_t *) interrupt_message->buffer; 
            network_address_t temp_address;
            unpack_address(received_header->source_address, temp_address);
            if (socket->remote_port_number == unpack_unsigned_short(received_header->source_port) &&
              network_compare_network_addresses(socket->remote_address, temp_address) != 0 &&
              received_header->message_type == MSG_ACK) {
              //same address, same ports, right message
              deregister_alarm(timeout_alarm_id); //only deregister alarm when the right packet is found
              connection_established = 1; 
              //queue_prepend(socket->acknowledgements, interrupt_message); //ack works as well when there is data 
              break;
            }
            else {
              free(interrupt_message);
            }
          }
        }
      }
      if (connection_established) { 
        //correct response has been found, get out of this timeout loop!
        break;
      }
    }
    //if timeout occurs, will loop back to initial waiting phase for MSG_SYN from client
  } 
  
  printf("leaving server create\n");
  //update server socket values with client connection
  socket->state = CONNECTED;
  assert(socket != NULL);
  return socket; 
}