Advertisement
pascallius

Untitled

Apr 15th, 2024
594
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.11 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <stddef.h>
  6. #include <assert.h>
  7. #include <poll.h>
  8. #include <errno.h>
  9. #include <time.h>
  10. #include <sys/time.h>
  11. #include <sys/socket.h>
  12. #include <sys/uio.h>
  13. #include <netinet/in.h>
  14.  
  15.  
  16. #include "rlib.h"
  17. #include "buffer.h"
  18.  
  19. #define miliseconds(n) 1000000 * n
  20.  
  21. static int checks(rel_t *r, packet_t *pkt, size_t n);
  22. static void process_ACK_PKG(rel_t *r, packet_t *pkt, size_t n);
  23. static void process_DATA_PKG(rel_t *r, packet_t *pkt, size_t n);
  24. static int is_duplicate(rel_t *r, packet_t *pkt);
  25. static long now_ms();
  26. static int get_send_window_size(rel_t *r);
  27. static void send_ACK_PKG(rel_t *r, uint32_t ack);
  28. static packet_t *create_DATA_PKG(rel_t *r);
  29.  
  30.  
  31. struct reliable_state {
  32.     rel_t *next;            /* Linked list for traversing all connections */
  33.     rel_t **prev;
  34.  
  35.     conn_t *c;          /* This is the connection object */
  36.  
  37.    
  38.     size_t window_size;
  39.     uint32_t next_seq;
  40.     int timeout;
  41.    
  42.     uint32_t  lowest_ackno;
  43.     uint32_t  send_nxt;
  44.     int send_eof;
  45.     int send_eof_acked;
  46.     int rec_eof;
  47.     uint32_t next_received;
  48.  
  49.  
  50.     //buffers
  51.     buffer_t* send_buffer;
  52.     buffer_t* rec_buffer;
  53.  
  54. };
  55. rel_t *rel_list;
  56.  
  57. // **********************Static helper functions Start***************
  58. static int get_send_window_size(rel_t *r){
  59.     return r->send_nxt - r->lowest_ackno;
  60. }
  61.  
  62. static long now_ms() {
  63.     struct timeval now;
  64.     gettimeofday(&now, NULL);
  65.     return now.tv_sec * 1000 + now.tv_usec / 1000;
  66. }
  67.  
  68. static int is_duplicate(rel_t *r, packet_t *pkt){
  69.     return ntohl(pkt->seqno) < r->next_received;
  70. }
  71. static int checks(rel_t *r, packet_t *pkt, size_t n){
  72.     int rcv_check = pkt->cksum;
  73.     pkt->cksum = 0;
  74.     if(ntohs(pkt->len)!= n){
  75.         return -1;
  76.     }
  77.     if(rcv_check != cksum(pkt,n)){
  78.         return -1;
  79.     }
  80.  
  81.     pkt->cksum = rcv_check;
  82.     return 0;
  83. }
  84.  
  85. static void send_ACK_PKG(rel_t *r, uint32_t ack){
  86.     struct ack_packet *a = xmalloc(sizeof(struct ack_packet));
  87.     a->cksum = 0;
  88.     a->len = htons(8);
  89.     a->ackno = htonl(ack);
  90.     a->cksum = cksum(a,8);
  91.     conn_sendpkt(r->c, (packet_t *)a, 8);
  92.     free(a);
  93.  
  94. }
  95.  
  96. static void process_ACK_PKG(rel_t *r, packet_t *pkt, size_t n){
  97.     if(buffer_size(r->send_buffer)==0) return;
  98.     if(ntohl(pkt->ackno)>r->lowest_ackno){ // send una?
  99.         r->lowest_ackno = ntohl(pkt->ackno);
  100.         buffer_remove(r->send_buffer, r->lowest_ackno);
  101.     }
  102.     if(r->send_eof){ // send eof?
  103.         if(buffer_size(r->send_buffer)==0) r->send_eof_acked = 1;
  104.     }
  105.     if (r->send_eof_acked && r->rec_eof && buffer_size(r->send_buffer)==0){
  106.         rel_destroy(r);
  107.  
  108.     }else if(get_send_window_size(r) < r->window_size){
  109.         rel_read(r);
  110.     }
  111.     return;
  112. }
  113.  
  114. static packet_t *create_DATA_PKG(rel_t *r){ //TODO
  115.     packet_t *pkt;
  116.     pkt = xmalloc(sizeof(packet_t));
  117.     int input = conn_input(r->c, pkt->data, 500);
  118.  
  119.     if (input == 0) {
  120.         free(pkt);
  121.         return NULL;
  122.     }
  123.    
  124.     pkt->cksum = 0;
  125.     pkt->len = htons(12 + ((input == -1) ? 0 : input));
  126.     pkt->ackno = htonl(r->next_received);
  127.     pkt->seqno = htonl(r->send_nxt);
  128.     pkt->cksum = cksum(pkt, ntohs(pkt->len));
  129.     return pkt;
  130. }
  131.  
  132. static void process_DATA_PKG(rel_t *r, packet_t *pkt, size_t n){
  133.  
  134. if (is_duplicate(r, pkt)) {
  135.         send_ACK_PKG(r, ntohl(pkt->seqno) + 1);
  136.         return;
  137.     }
  138.  
  139.     if (r->rec_eof) {
  140.         if (r->send_eof_acked) rel_destroy(r);
  141.         return;
  142.     }
  143.  
  144.     // ignore out-of-window packets
  145.     if (ntohl(pkt->seqno) >= r->next_received + r->window_size) return;
  146.  
  147.     if (buffer_size(r->rec_buffer) == r->window_size) {
  148.         rel_output(r);
  149.     }
  150.  
  151.     // store in buffer if not already there
  152.     if (!buffer_contains(r->rec_buffer, ntohl(pkt->seqno))) {
  153.         buffer_insert(r->rec_buffer, pkt, now_ms());
  154.     }
  155.  
  156.     rel_output(r);
  157. }
  158. // **********************Static helper functions END***************
  159.  
  160. rel_t *
  161. rel_create (conn_t *c, const struct sockaddr_storage *ss,
  162. const struct config_common *cc)
  163. {
  164.     rel_t *r;
  165.  
  166.     r = xmalloc (sizeof (*r));
  167.     memset (r, 0, sizeof (*r));
  168.  
  169.     if (!c) {
  170.         c = conn_create (r, ss);
  171.         if (!c) {
  172.             free (r);
  173.             return NULL;
  174.         }
  175.     }
  176.  
  177.     r->c = c;
  178.     r->next = rel_list;
  179.     r->prev = &rel_list;
  180.     if (rel_list)
  181.     rel_list->prev = &r->next;
  182.     rel_list = r;
  183.  
  184.     r->send_buffer = xmalloc(sizeof(buffer_t));
  185.     r->send_buffer->head = NULL;
  186.     r->lowest_ackno = 1;
  187.     r->send_nxt = 1;
  188.     r->send_eof = 0;
  189.     r->send_eof_acked = 0;
  190.  
  191.     // receive
  192.     r->rec_buffer = xmalloc(sizeof(buffer_t));
  193.     r->rec_buffer->head = NULL;
  194.     r->next_received = 1;
  195.     r->rec_eof = 0;
  196.  
  197.     r->window_size = cc->window;
  198.     r->timeout = cc->timeout;
  199.  
  200.     return r;
  201. }
  202.  
  203. void
  204. rel_destroy (rel_t *r)
  205. {
  206.     if (r->next) {
  207.         r->next->prev = r->prev;
  208.     }
  209.     *r->prev = r->next;
  210.     conn_destroy (r->c);
  211.     buffer_clear(r->send_buffer);
  212.     free(r->send_buffer);
  213.     buffer_clear(r->rec_buffer);
  214.     free(r->rec_buffer);
  215.     free(r);
  216.  
  217. }
  218.  
  219.  
  220. void
  221. rel_recvpkt (rel_t *r, packet_t *pkt, size_t n)
  222. {
  223.     if(checks(r,pkt,n)==-1) return;
  224.  
  225.     // if its only an ACK packet
  226.     if(n==8){
  227.         process_ACK_PKG(r, pkt, n);
  228.     }else{
  229.         process_DATA_PKG(r, pkt, n);
  230.     }
  231.  
  232.  
  233. }
  234.  
  235. void
  236. rel_read (rel_t *s)
  237. {
  238.     /*
  239.     char buffer[s->window_size];
  240.     int size = conn_input(s->c,buffer,conn_bufspace(s->c));
  241.     if(size==0||size==-1){
  242.         return NULL;
  243.     }
  244.  
  245.     packet_t *pkt = malloc(sizeof(*pkt));
  246.  
  247.     // first only process packets which fit into the packet
  248.     int off = 0;
  249.     if(size < 500){
  250.         build_packet(pkt, size + 12);
  251.         strncpy(pkt->data, &buffer[0],size); //TODO change offset here
  252.     }else{
  253.         printf("Too large packet in rel_read");
  254.     }
  255.     //TODO: implement for larger input
  256.  
  257.     free(pkt);
  258.     */
  259.    {
  260.     // read and send as long as:
  261.     // 1. send window is not full, and
  262.     // 2. no EOF has been read from stdin
  263.     while ((get_send_window_size(s) < s->window_size) && !s->send_eof) {
  264.         packet_t *pkt = create_DATA_PKG(s);
  265.  
  266.         // if stdin is empty, return
  267.         if (pkt == NULL) return;
  268.  
  269.         // set flag if EOF has been read from stdin
  270.         if (ntohs(pkt->len) == 12) s->send_eof = 1;
  271.  
  272.         conn_sendpkt(s->c, pkt, ntohs(pkt->len));
  273.         buffer_insert(s->send_buffer, pkt, now_ms());
  274.         free(pkt);
  275.         s->send_nxt++;
  276.     }
  277. }
  278.  
  279. }
  280.  
  281. void
  282. rel_output (rel_t *r)
  283. {  
  284.  
  285.     //not empty
  286.     if(buffer_size(r->rec_buffer)!=0){
  287.         buffer_node_t* node = buffer_get_first(r->rec_buffer);
  288.         size_t free_b = conn_bufspace(r->c);
  289.         size_t used = 0;
  290.         uint32_t num_b = 0;
  291.         int out_size;
  292.         while(node&&num_b<(r->window_size)){
  293.             if (!buffer_contains(r->rec_buffer, r->next_received) || r->next_received != ntohl(node->packet.seqno)) break;
  294.             uint16_t payload_size = ntohs(node->packet.len) - 12;
  295.             if (used + payload_size > free_b) break;
  296.             if(payload_size==0) r->rec_eof =1;
  297.  
  298.             out_size = conn_output(r->c,node->packet.data,payload_size);
  299.             assert(out_size>=0);
  300.             used += payload_size;
  301.             r->next_received++;
  302.             node = node->next;
  303.             buffer_remove_first(r->rec_buffer);
  304.  
  305.             num_b++;
  306.         }
  307.  
  308.         //ackno
  309.         send_ACK_PKG(r, r->next_received);
  310.     }else{
  311.         if(r->send_eof_acked){
  312.             rel_destroy(r);
  313.         }
  314.         return;
  315.     }
  316. }
  317.  
  318. void
  319. rel_timer ()
  320. {
  321.     rel_t *current = rel_list;
  322.     struct timespec now;
  323.     while (current != NULL) {
  324.         for(buffer_node_t* node = buffer_get_first(current->send_buffer);node;node=node->next){
  325.             if(clock_gettime(CLOCK_MONOTONIC,&now)==-1) return;
  326.             if(miliseconds(now.tv_nsec) - (node->last_retransmit)>current->timeout){
  327.                 node->last_retransmit = miliseconds(now.tv_nsec);
  328.                 conn_sendpkt(current->c,&node->packet,ntohs(node->packet.len));
  329.             }
  330.  
  331.  
  332.  
  333.         }
  334.         current = current->next;
  335.     }
  336. }
  337.  
  338.  
  339.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement