From 5e56c37f2d93aca545f4a00a8c57d995d417fc4d Mon Sep 17 00:00:00 2001
From: ingenzi <vany.ingenzi@student.uclouvain.be>
Date: Thu, 17 Mar 2022 20:13:46 +0100
Subject: [PATCH] Advanced on the receiver

---
 headers/receiver_utils.h |  16 +++++
 src/our_utils.c          |   2 +-
 src/receiver.c           |  17 ++----
 src/receiver_utils.c     | 128 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 149 insertions(+), 14 deletions(-)
 create mode 100644 src/receiver_utils.c

diff --git a/headers/receiver_utils.h b/headers/receiver_utils.h
index a5cc853..572e45a 100644
--- a/headers/receiver_utils.h
+++ b/headers/receiver_utils.h
@@ -7,4 +7,20 @@
 #ifndef __RECEIVER_UTILS_
 #define __RECEIVER_UTILS_
 
+/* We are using 8 bits to encode the seqnum therefore to fight redondance our window is of 2**(8)/2 */
+#define MAX_SELECTIVE_REPEAT_WINDOW 8 
+
+/* Represent the receiver's connection state */
+typedef struct __attribute__((__packed__))
+{
+} con_state_t;
+
+
+/**
+ * Loop reading on socket and printing to the stdout
+ * @sfd : The socket file descriptor. It is both bound and connected.
+ * @return: as soon as the whole transfer is done.
+ */
+void receiver_read_write_loop(int sfd);
+
 #endif
\ No newline at end of file
diff --git a/src/our_utils.c b/src/our_utils.c
index b81e2f8..45e6305 100644
--- a/src/our_utils.c
+++ b/src/our_utils.c
@@ -78,7 +78,7 @@ int create_socket_connect(struct sockaddr_in6 * dest_addr)
 
 int create_socket(struct sockaddr_in6 *source_addr, int src_port, struct sockaddr_in6 *dest_addr, int dst_port)
 {
-    if        ( source_addr != NULL && dest_addr == NULL )
+    if ( source_addr != NULL && dest_addr == NULL )
     {
         source_addr->sin6_port = htons(src_port);
         return create_socket_bind(source_addr);
diff --git a/src/receiver.c b/src/receiver.c
index dbb84be..9afa977 100644
--- a/src/receiver.c
+++ b/src/receiver.c
@@ -13,7 +13,7 @@
 #include "log.h"
 #include "packet_interface.h"
 #include "our_utils.h"
-
+#include "receiver_utils.h"
 
 int print_usage(char *prog_name) {
     ERROR("Usage:\n\t%s [-s stats_filename] listen_ip listen_port", prog_name);
@@ -73,20 +73,11 @@ int main(int argc, char **argv) {
         ERROR("An error occured when creating the socket\n");
         return (EXIT_FAILURE);
     }
-    // 2. Wait for a client 
-    char * buff[PKT_MAX_LEN];
-    ssize_t len;
-    int err  = wait_for_client(socket, PKT_MAX_LEN,(char *)buff, &len);
-    if (err == 0)
-    {
-        close(socket);
-        return (EXIT_FAILURE);
-    }
-
-    DEBUG_DUMP(buff, len);
 
-    // 3. Start listening till end 
+    ASSERT(stats_filename == NULL);
 
+    receiver_read_write_loop(socket);
     close(socket);
+
     return EXIT_SUCCESS;
 }
\ No newline at end of file
diff --git a/src/receiver_utils.c b/src/receiver_utils.c
new file mode 100644
index 0000000..9722c55
--- /dev/null
+++ b/src/receiver_utils.c
@@ -0,0 +1,128 @@
+
+#include "log.h"
+#include "packet_interface.h"
+#include <poll.h>
+#include "our_utils.h"
+#include "receiver_utils.h"
+
+int send_data_if_inneed()
+{
+    return 1;
+}
+
+int handle_incoming_data()
+{
+    /*
+    char * buff;
+    ssize_t read_bytes = read(pfd->fd, (void *) buff, MAX_SIZE);
+    if (read_bytes == -1)
+        return 0;
+    err = fwrite((void *) buff, sizeof(char), read_bytes, stdout);
+    if (err == 0)
+        return 0;
+    err = fflush(stdout);
+    */
+    return 1;
+}
+
+int handle_revents(struct pollfd * pfd)
+{
+    DEBUG(" events: %s%s%s%s",
+            (pfd->revents & POLLIN)  ? "POLLIN "   : "",
+            (pfd->revents & POLLOUT) ? "POLLOUT "  : "",
+            (pfd->revents & POLLHUP) ? "POLLHUP "  : "",
+            (pfd->revents & POLLERR) ? "POLLERR "  : "");
+
+    if (pfd->revents & POLLIN)          /* POLLIN : There's data to read */
+    {
+        return handle_incoming_data();
+    } else if (pfd->revents & POLLHUP)  /* POLLHUP : The other user disconnected from their side */
+    {
+        DEBUG("The sender disconnected.");
+        return 0;
+    } else if (pfd->revents & POLLOUT)  /* POLLOUT : Possible to send that */
+    {
+        return send_data_if_inneed();
+    } else {                            /* POLLERR : An error occurred */   
+        ERROR("Poll revents marks error.");
+        return 0;
+    }
+    return 1;
+}
+
+void reception_loop(struct pollfd * pfd, con_state_t * state, pkt_t * pkt)
+{    
+    ASSERT(state != NULL || pkt != NULL);
+    int not_eof = 1;
+    while (not_eof)
+    {
+        int ready = poll(pfd, 1, -1);
+        if (ready == -1)
+            return;
+
+        if (pfd->revents != 0)
+            not_eof = handle_revents(pfd);
+    }
+}
+
+/**
+ * Waits for a client to send data to the socket and then connectes to the client
+ * @return: 0 upon success, -1 in case of an error. a message will be displayed to the stderr
+ */
+int connect_to_a_client(int sfd, pkt_t * init_pkt)
+{
+    char * buffer[PKT_MAX_LEN];
+    ssize_t written_in_buffer;
+    // We suppose that the first contact is going to be our client no need to check for more
+    int err  = wait_for_client(sfd, PKT_MAX_LEN, (char *)buffer, &written_in_buffer);
+    if (err != 0) return -1;
+
+    DEBUG_DUMP(buffer, written_in_buffer);
+    pkt_status_code status = pkt_decode((char *) buffer, (size_t) written_in_buffer, init_pkt); 
+    if (status != PKT_OK)
+    {
+        ERROR("When encoding the init_packet got pkt_status = %d", status);
+        return -1;
+    } 
+    return 0;
+}
+
+/**
+ * This main loop for the receiver.
+ * @sfd: A valid socket.
+ * @return: As soon as an error occurs or, a the total transfer came through.
+ */
+void receiver_read_write_loop(int sfd)
+{
+    pkt_t * pkt = pkt_new();
+    con_state_t * state = malloc(sizeof(con_state_t)); 
+    struct pollfd * pfd = (struct pollfd *) calloc(1, sizeof(struct pollfd));
+    if (pkt == NULL || state == NULL || pfd == NULL) return;
+
+    pfd->fd             = sfd; 
+    pfd->events         = POLLIN | POLLOUT;
+
+    int err = connect_to_a_client(sfd, pkt);
+    if (err == 0)
+        return;
+    // Handle initial packet.
+
+    err = fwrite((void *) pkt_get_payload(pkt), sizeof(char), pkt_get_length(pkt), stdout);
+    err = fflush(stdout);
+
+    /*
+    if (err == 0) 
+        reception_loop(pfd, state, pkt);
+    */
+
+    char * buffer[PKT_MAX_LEN];
+    size_t len = PKT_MAX_LEN;
+
+    err = pkt_encode(pkt, (char *) buffer, &len);
+    if (err == 0)
+        err = write(pfd->fd, (void *) buffer, len);
+
+    pkt_del(pkt);
+    free(state);
+    free(pfd);
+}
\ No newline at end of file
-- 
GitLab