src/mrt.c
// mrt_open: start listening on specified port for UDP packets
// ip_addr is a placeholder for ip address
start listening on specified port for UDP packets
ip_addr is a placeholder for ip address
start listening on specified port for UDP packets ip_addr is a placeholder for ip address
mrt_serv_conn * mrt_open(int ip_addr, int PORT_NUM, int size) {
  int i, n, pid;
  mrt_serv_conn * rc = (mrt_serv_conn *)malloc(sizeof(mrt_serv_conn));
  int sockfd;
  socklen_t len;
  struct sockaddr_in servaddr, cliaddr; 
  mrt_packet * pkt; 
  mrt_connection * conn;
  setbuf(stdout, (char *)0);
  if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { 
      perror("socket creation failed"); 
      exit(EXIT_FAILURE); 
  } 
  memset(&servaddr, 0, sizeof(servaddr)); 
  memset(&cliaddr, 0, sizeof(cliaddr)); 
  servaddr.sin_family    = AF_INET; 
  servaddr.sin_addr.s_addr = INADDR_ANY; 
  servaddr.sin_port = htons(PORT_NUM); 
  if ( bind(sockfd, (const struct sockaddr *)&servaddr,  
          sizeof(servaddr)) < 0 ) { 
      perror("bind failed"); 
      exit(EXIT_FAILURE); 
  }
  rc->fd = sockfd;
  rc->size = size;
  rc->conns = mmap(NULL, size * sizeof(mrt_connection), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  conn_init(rc->conns, size);
  len = sizeof(cliaddr);  
  if (!(pid = fork())) {
    pkt = (mrt_packet *)malloc(sizeof(mrt_packet));
    memset(pkt, 0, sizeof(mrt_packet));
    while ((n = recvfrom(sockfd, (char *)pkt, sizeof(mrt_packet),  
              MSG_WAITALL, ( struct sockaddr *) &cliaddr, 
              &len)) != -1) {
      if (MRT_TEST) print_pkt(pkt);
      if (!pkt->header.flags && strcmp(pkt->header.chksum, get_md5(pkt->data))) {
        printf("corrupted packet: discarded\n");
        continue;
      }
      conn = NULL;
      for (i = 0; i < size; i++) 
        if (addr_is_equal(cliaddr, rc->conns[i].addr)) {
          if (MRT_TEST) printf("Got a match!\n");
          conn = &rc->conns[i];
          if (conn->active) {
            if (MRT_TEST) printf("Got an active match!\n");
            switch(pkt->header.flags) {
              case FLAG_SYN:
                conn->offset = pkt->header.seq;
                conn->nextseq = 0;
                send_ctrl_pkt(sockfd, &cliaddr, FLAG_SYN | FLAG_ACK, conn->nextseq + conn->offset, rb_size(&conn->rb));
                break;
              case FLAG_FIN:
                if (MRT_TEST) printf("Sending FIN ACK...\n");
                send_ctrl_pkt(sockfd, &cliaddr, FLAG_FIN | FLAG_ACK, 0, 0);
                conn_init(conn, 1);
                break;
              case 0:
                if (rb_full(&conn->rb)){
                  send_ctrl_pkt(sockfd, &cliaddr, FLAG_ACK, conn->nextseq + conn->offset, 0);
                } else {
                  if (pkt->header.seq - conn->offset == conn->nextseq) {
                    if (MRT_TEST) printf("One packet saved!\n");
                    conn->nextseq++;
                    rb_push(&conn->rb, pkt->header.seq - conn->offset, pkt->data, MSS);
                    if (MRT_TEST) printf("Current rcvwnd: %d.\n", rb_size(&conn->rb));
                    send_ctrl_pkt(sockfd, &cliaddr, FLAG_ACK, conn->nextseq + conn->offset, rb_size(&conn->rb));
                  } else send_ctrl_pkt(sockfd, &cliaddr, FLAG_ACK, conn->nextseq + conn->offset, rb_size(&conn->rb));
                }
                break;
            }    
          }
          break;
        }
      if (!conn) {
        if (MRT_TEST) printf("Not connected user!\n");
        switch(pkt->header.flags) {
          case FLAG_FIN:
            send_ctrl_pkt(sockfd, &cliaddr, FLAG_FIN | FLAG_ACK, 0, 0);
            break;
          case FLAG_SYN:
            for (i = 0; i < size; i++) 
              if (!rc->conns[i].initialized) {
                if (MRT_TEST) printf("One incoming connection saved.\n");
                conn = &rc->conns[i];
                conn->initialized = 1;
                conn->offset = pkt->header.seq;
                memcpy(&conn->addr, &cliaddr, sizeof(struct sockaddr_in));
                conn->fd = sockfd;
                break;
              }
        }
      }
      memset(pkt, 0, sizeof(mrt_packet));
    }
    free(pkt);
    exit(0);
  }
  rc->pid = pid;
  return rc;
}
mrt_serv_conn * mrt_open ( int ip_addr , int PORT_NUM , int size ) { int i , n , pid ; mrt_serv_conn * rc = ( mrt_serv_conn * ) malloc ( sizeof ( mrt_serv_conn ) ) ; int sockfd ; socklen_t len ; struct sockaddr_in servaddr , cliaddr ; mrt_packet * pkt ; mrt_connection * conn ; setbuf ( stdout , ( char * ) 0 ) ; if ( ( sockfd = socket ( AF_INET , SOCK_DGRAM , 0 ) ) < 0 ) { perror ( " " ) ; exit ( EXIT_FAILURE ) ; } memset ( & servaddr , 0 , sizeof ( servaddr ) ) ; memset ( & cliaddr , 0 , sizeof ( cliaddr ) ) ; servaddr . sin_family = AF_INET ; servaddr . sin_addr . s_addr = INADDR_ANY ; servaddr . sin_port = htons ( PORT_NUM ) ; if ( bind ( sockfd , ( const struct sockaddr * ) & servaddr , sizeof ( servaddr ) ) < 0 ) { perror ( " " ) ; exit ( EXIT_FAILURE ) ; } rc -> fd = sockfd ; rc -> size = size ; rc -> conns = mmap ( NULL , size * sizeof ( mrt_connection ) , PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANONYMOUS , -1 , 0 ) ; conn_init ( rc -> conns , size ) ; len = sizeof ( cliaddr ) ; if ( ! ( pid = fork ( ) ) ) { pkt = ( mrt_packet * ) malloc ( sizeof ( mrt_packet ) ) ; memset ( pkt , 0 , sizeof ( mrt_packet ) ) ; while ( ( n = recvfrom ( sockfd , ( char * ) pkt , sizeof ( mrt_packet ) , MSG_WAITALL , ( struct sockaddr * ) & cliaddr , & len ) ) != -1 ) { if ( MRT_TEST ) print_pkt ( pkt ) ; if ( ! pkt -> header . flags && strcmp ( pkt -> header . chksum , get_md5 ( pkt -> data ) ) ) { printf ( " \n " ) ; continue ; } conn = NULL ; for ( i = 0 ; i < size ; i ++ ) if ( addr_is_equal ( cliaddr , rc -> conns [ i ] . addr ) ) { if ( MRT_TEST ) printf ( " \n " ) ; conn = & rc -> conns [ i ] ; if ( conn -> active ) { if ( MRT_TEST ) printf ( " \n " ) ; switch ( pkt -> header . flags ) { case FLAG_SYN : conn -> offset = pkt -> header . seq ; conn -> nextseq = 0 ; send_ctrl_pkt ( sockfd , & cliaddr , FLAG_SYN | FLAG_ACK , conn -> nextseq + conn -> offset , rb_size ( & conn -> rb ) ) ; break ; case FLAG_FIN : if ( MRT_TEST ) printf ( " \n " ) ; send_ctrl_pkt ( sockfd , & cliaddr , FLAG_FIN | FLAG_ACK , 0 , 0 ) ; conn_init ( conn , 1 ) ; break ; case 0 : if ( rb_full ( & conn -> rb ) ) { send_ctrl_pkt ( sockfd , & cliaddr , FLAG_ACK , conn -> nextseq + conn -> offset , 0 ) ; } else { if ( pkt -> header . seq - conn -> offset == conn -> nextseq ) { if ( MRT_TEST ) printf ( " \n " ) ; conn -> nextseq ++ ; rb_push ( & conn -> rb , pkt -> header . seq - conn -> offset , pkt -> data , MSS ) ; if ( MRT_TEST ) printf ( " \n " , rb_size ( & conn -> rb ) ) ; send_ctrl_pkt ( sockfd , & cliaddr , FLAG_ACK , conn -> nextseq + conn -> offset , rb_size ( & conn -> rb ) ) ; } else send_ctrl_pkt ( sockfd , & cliaddr , FLAG_ACK , conn -> nextseq + conn -> offset , rb_size ( & conn -> rb ) ) ; } break ; } } break ; } if ( ! conn ) { if ( MRT_TEST ) printf ( " \n " ) ; switch ( pkt -> header . flags ) { case FLAG_FIN : send_ctrl_pkt ( sockfd , & cliaddr , FLAG_FIN | FLAG_ACK , 0 , 0 ) ; break ; case FLAG_SYN : for ( i = 0 ; i < size ; i ++ ) if ( ! rc -> conns [ i ] . initialized ) { if ( MRT_TEST ) printf ( " \n " ) ; conn = & rc -> conns [ i ] ; conn -> initialized = 1 ; conn -> offset = pkt -> header . seq ; memcpy ( & conn -> addr , & cliaddr , sizeof ( struct sockaddr_in ) ) ; conn -> fd = sockfd ; break ; } } } memset ( pkt , 0 , sizeof ( mrt_packet ) ) ; } free ( pkt ) ; exit ( 0 ) ; } rc -> pid = pid ; return rc ; }
mrt_open: start listening on specified port for UDP packets
ip_addr is a placeholder for ip address
mrt_open : start listening on specified port for UDP packets ip_addr is a placeholder for ip address
// mrt_serv_conn * rc = mmap(NULL, sizeof(mrt_serv_conn), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); // to store incoming packets // Creating socket file descriptor  // setup addresses // Filling server information  // IPv4  // Bind the socket with the server address  // initialize rc // rc->conns = (mrt_connection *)malloc(size * sizeof(mrt_connection)); // cliaddr for sender identifying //len is value/result  // fork - return the mrt_serv_conn //  child handles all the incoming packets // initialize pkt first // check validity first // packet is valid // the sender has reached the server before // if the packet is from an initialized and active connection // this suggests that the sent ack was lost/had not arrived // immediately resend the ack // sender disconnecting // send FIN ACK // wipe out conn // regular data // buffer not full // if seq == nextseq // add the packet to the ht - ! sync here // nextseq++ // update rcvwnd // buffer is full // discard packet, resend ack with rcvwnd = 0 // the connection is not active, ignore // not record of sender // an unrecognized FIN request, possibly due to a lost FIN ACK // resend a FIN ACK to the sender // a SYN request // find a spot for them // an empty spot, set initialized and cliaddr for that connection, no ack sent yet // all occupied, reject service // clean up