diff --git a/headers/our_utils.h b/headers/our_utils.h
index 8647c5ccc90e9c90280e64d3315f6d6ed13741c0..421c0dae01cc65dc592bf4cadfe457a498f5519a 100644
--- a/headers/our_utils.h
+++ b/headers/our_utils.h
@@ -44,11 +44,11 @@ int create_socket(struct sockaddr_in6 *source_addr, int src_port, struct sockadd
 /* Block the caller until a message is received on sfd,
  * and connect the socket to the source addresse of the received message
  * @sfd: a file descriptor to a bound socket but not yet connected
- * @buffer : a non null buffer where it writes the received message.
- * @len: after reading the message it sents the amount bytes read in len.
  * @return: 0 in case of success, -1 otherwise
+ * @POST: This call is idempotent, it does not 'consume' the data of the message,
+ * and could be repeated several times blocking only at the first call.
  */
-int wait_for_client(int sfd, int MAX_MESSAGE_SIZE, char * buffer, ssize_t * len);
+int wait_for_client(int sfd);
 
 
 #endif
\ No newline at end of file
diff --git a/headers/receiver.h b/headers/receiver.h
index c1fcb39dc5a5e3a8f6b3b68c0b849b86fbd58fdc..7bdbfea3ecaa2589d31346efa7d1a7ae6be47111 100644
--- a/headers/receiver.h
+++ b/headers/receiver.h
@@ -1,4 +1,25 @@
 /**
  * @file receiver.h
  * @brief   This header contains all the structures and functions definitions that ae going to be used by the receiver.c 
- */
\ No newline at end of file
+ */
+
+#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/headers/receiver_utils.h b/headers/receiver_utils.h
deleted file mode 100644
index 572e45a56d126586e1b7d0858a2d9d6410708ff3..0000000000000000000000000000000000000000
--- a/headers/receiver_utils.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * @file receiver_utils.h
- * @brief This header contains utils will be used by the receiver
- * @date 2022-03-17
- */
-
-#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/receiver b/receiver
new file mode 100755
index 0000000000000000000000000000000000000000..719d1d48efb0681ed0c3ffc65d75b512bda1a658
Binary files /dev/null and b/receiver differ
diff --git a/sender b/sender
new file mode 100755
index 0000000000000000000000000000000000000000..d9d0d784c392e7d8abde67d555244cfa9bef5cc1
Binary files /dev/null and b/sender differ
diff --git a/src/our_utils.c b/src/our_utils.c
index 0628f0102d40987a9084981633ff6a97bbbddc25..c07a716fce1e74ec34a929dadbdb637e76160481 100644
--- a/src/our_utils.c
+++ b/src/our_utils.c
@@ -89,22 +89,18 @@ int create_socket(struct sockaddr_in6 *source_addr, int src_port, struct sockadd
     return -1;
 }
 
-
-int wait_for_client(int sfd, int MAX_MESSAGE_SIZE, char * buffer, ssize_t * len)
+int wait_for_client(int sfd)
 {
+    int MAX_MESSAGE_SIZE = 1024;
+    uint8_t buff[MAX_MESSAGE_SIZE];   // allocate the receive buffer on the stack
     struct sockaddr_storage peer_addr;  // allocate the peer's address on the stack. It will be initialized when we receive a message
     socklen_t peer_addr_len = sizeof(struct sockaddr_storage); // variable that will contain the length of the peer's address
-    *len = recvfrom(sfd, buffer, MAX_MESSAGE_SIZE, MSG_PEEK, (struct sockaddr *) &peer_addr, &peer_addr_len);
-    if (*len == -1)
-    { 
-        ERROR("On recvfrom while waiting for client");
+    ssize_t amount_read = recvfrom(sfd, buff, MAX_MESSAGE_SIZE, MSG_PEEK, (struct sockaddr *) &peer_addr, &peer_addr_len);
+    if (amount_read == -1){ 
         return -1;
     }
-    int err = connect(sfd, (struct sockaddr *) &peer_addr, sizeof(struct sockaddr_storage));
+    int err             = connect(sfd, (struct sockaddr *) &peer_addr, sizeof(struct sockaddr_storage));
     if (err != EISCONN && err != 0)
-    {
-        ERROR("When connecting to client");
         return -1;
-    }
     return 0;
 }
\ No newline at end of file
diff --git a/src/receiver.c b/src/receiver.c
index 9afa9775c19c30501c8e0ad4911c8c7b5c27e1b1..ef5a129cefc927ba0adcef2cf69e55202a3d4161 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"
+#include "receiver.h"
 
 int print_usage(char *prog_name) {
     ERROR("Usage:\n\t%s [-s stats_filename] listen_ip listen_port", prog_name);
diff --git a/src/receiver_utils.c b/src/receiver_utils.c
index 9722c5553688598aa98af498046b537a024626fc..fdb3e2257aeb2983d173747537e5c3d85a4f5f5d 100644
--- a/src/receiver_utils.c
+++ b/src/receiver_utils.c
@@ -3,7 +3,7 @@
 #include "packet_interface.h"
 #include <poll.h>
 #include "our_utils.h"
-#include "receiver_utils.h"
+#include "receiver.h"
 
 int send_data_if_inneed()
 {
@@ -74,7 +74,7 @@ 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);
+    int err  = wait_for_client(sfd);
     if (err != 0) return -1;
 
     DEBUG_DUMP(buffer, written_in_buffer);
@@ -105,6 +105,7 @@ void receiver_read_write_loop(int sfd)
     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);
diff --git a/temp/get_ipv6_address.c b/temp/get_ipv6_address.c
new file mode 100644
index 0000000000000000000000000000000000000000..d7f38800d1fe5a4f9ffbd3668b819e0c5efa9e27
--- /dev/null
+++ b/temp/get_ipv6_address.c
@@ -0,0 +1,253 @@
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <poll.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+/*************************** Utilities ******************************/
+
+
+/*************************** Start Q1 *******************************/
+/* Resolve the resource name to an usable IPv6 address
+ * @address: The name to resolve
+ * @rval: Where the resulting IPv6 address descriptor should be stored
+ * @return: NULL if it succeeded, or a pointer towards
+ *          a string describing the error if any.
+ *          (const char* means the caller cannot modify or free the return value,
+ *           so do not use malloc!)
+ */
+const char * real_address(const char *address, struct sockaddr_in6 *rval)
+{
+    struct addrinfo hints;
+    struct addrinfo *result; 
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_INET6;     
+    hints.ai_socktype = SOCK_DGRAM;
+    hints.ai_flags  = AI_CANONNAME; 
+    hints.ai_protocol = 0;
+    int res = getaddrinfo(address, NULL, &hints, &result);
+    if ( res != 0 )
+        return gai_strerror(res);
+    rval = (struct sockaddr_in6 *) memcpy( (void *) rval, result->ai_addr, sizeof(struct sockaddr_in6));
+    freeaddrinfo(result);
+    return NULL;
+}
+/*************************** End Q1 *******************************/
+
+/*************************** Start Q2 *****************************/
+void ipv6_to_str_unexpanded(char *str, const struct in6_addr *addr) {
+   sprintf(str, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+                 (int)addr->s6_addr[0], (int)addr->s6_addr[1],
+                 (int)addr->s6_addr[2], (int)addr->s6_addr[3],
+                 (int)addr->s6_addr[4], (int)addr->s6_addr[5],
+                 (int)addr->s6_addr[6], (int)addr->s6_addr[7],
+                 (int)addr->s6_addr[8], (int)addr->s6_addr[9],
+                 (int)addr->s6_addr[10], (int)addr->s6_addr[11],
+                 (int)addr->s6_addr[12], (int)addr->s6_addr[13],
+                 (int)addr->s6_addr[14], (int)addr->s6_addr[15]);
+}
+
+int create_socket_bind(struct sockaddr_in6 * source_addr)
+{
+    // TODO: Create a IPv6 socket supporting datagrams
+    int sock = socket(AF_INET6, SOCK_DGRAM, 0);
+    // TODO: Bind it to the source
+    int err  = bind(sock, (struct sockaddr *) source_addr, sizeof(struct sockaddr_in6));
+    if (err == -1) 
+        return -1;
+
+    char text[100];
+    ipv6_to_str_unexpanded(text, &(source_addr->sin6_addr));
+    //const char * addr_str = inet_ntop(AF_INET6, (void *) &(source_addr->sin6_addr), text, 100);
+    fprintf(stderr, "Successfully bound to IPv6 address : %s, port : %d\n", text, ntohs(source_addr->sin6_port));
+    return sock;
+}
+
+int create_socket_connect(struct sockaddr_in6 * dest_addr)
+{
+    int sock = socket(AF_INET6, SOCK_DGRAM, 0);
+    int err  = connect(sock, (struct sockaddr *) dest_addr, sizeof(*dest_addr));
+    if (err == -1) 
+        return -1;
+    char text[100];
+    ipv6_to_str_unexpanded(text, &(dest_addr->sin6_addr));
+    fprintf(stderr, "Successfully connected to IPv6 addresss: %s, port : %d\n", text, ntohs(dest_addr->sin6_port));
+    return sock;
+}
+
+/* Creates a socket and initialize it
+ * @source_addr: if !NULL, the source address that should be bound to this socket
+ * @src_port: if >0, the port on which the socket is listening
+ * @dest_addr: if !NULL, the destination address to which the socket should send data
+ * @dst_port: if >0, the destination port to which the socket should be connected
+ * @return: a file descriptor number representing the socket,
+ *         or -1 in case of error (explanation will be printed on stderr)
+ */
+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 )
+    {
+        source_addr->sin6_port = htons(src_port);
+        return create_socket_bind(source_addr);
+    } else if ( source_addr == NULL && dest_addr != NULL ){
+        dest_addr->sin6_port   = htons(dst_port);
+        return create_socket_connect(dest_addr);
+    }
+    return -1;
+}
+/*************************** End Q2 *******************************/
+
+/*************************** Start Q3 *****************************/
+
+int handle_event(struct pollfd * pfd, ssize_t MAX_SIZE, char * buff)
+{
+    if (pfd->revents & POLLIN){
+        ssize_t read_bytes = read(pfd->fd, (void *) buff, MAX_SIZE);
+        if (read_bytes == -1)
+            return 0;
+        size_t err = fwrite("Incoming : \n\t", sizeof(char), 14, stderr);
+        err = fflush(stderr);
+        err = fwrite((void *) buff, sizeof(char), read_bytes, stdout);
+        if (err == 0)
+            fprintf(stderr, "Nonesense\n");
+        err = fflush(stdout);
+        return 1;
+    } else if (pfd->events & POLLHUP){ /*EOF or Error*/
+        fprintf(stderr, "Error...\n");
+        return 0;
+    } else {        /* POLLOUT */
+        size_t err;
+        size_t read_bytes = fread(buff, sizeof(char), MAX_SIZE, stdin);
+        if (read_bytes != 0)
+        {
+            err = write(pfd->fd, (void *) buff, read_bytes);
+            if (err == 0)
+                return 0;
+            err = fwrite("\n Sent\n", sizeof(char), 8, stderr);
+        }
+        err = fflush(stderr);
+        return 1;
+    }
+}
+
+/* Loop reading a socket and printing to stdout,
+ * while reading stdin and writing to the socket
+ * @sfd: The socket file descriptor. It is both bound and connected.
+ * @return: as soon as stdin signals EOF
+ */
+void read_write_loop(int sfd)
+{
+    struct pollfd * pfds;
+    pfds = (struct pollfd *) calloc(2, sizeof(struct pollfd));
+    if (pfds == NULL)
+        return;
+    pfds[0].fd              = sfd; 
+    pfds[0].events          = POLLIN | POLLOUT;
+
+    pfds[1].fd              = 0;        // stdin is defined to be file descriptor 0
+    pfds[1].events          = POLLIN ;
+
+    int nb_open_fds         = 2;
+    int MAX_SIZE            = 1024;     // Bytes
+    char buff[MAX_SIZE];
+    size_t writen;
+    while (nb_open_fds > 1)
+    {
+        int ready = poll(pfds, 2, -1);
+        if (ready == -1)
+            return;
+        
+        if (pfds[0].revents & POLLIN){
+            ssize_t read_bytes = read(pfds[0].fd, (void *) buff, MAX_SIZE);
+            if (read_bytes == -1)
+                return;
+            writen = fwrite((void *) buff, sizeof(char), read_bytes, stdout);
+            writen = fflush(stdout);
+        } else if ((pfds[0].revents & POLLHUP) || (pfds[0].revents & POLLERR)){ 
+            nb_open_fds--;
+        } else if ((pfds[0].revents & POLLOUT) && (pfds[1].revents & POLLIN)){ 
+            size_t read_bytes = fread(buff, sizeof(char), 1, stdin);
+            writen = fflush(stdin);
+            writen = write(pfds[0].fd, (void *) buff, read_bytes);
+            size_t e = -1;
+            if (writen == e || feof(stdin) != 0)
+                return;       
+        }
+    }
+}
+/*************************** End Q3 *******************************/
+
+/*************************** Start Q4 *****************************/
+
+/* Block the caller until a message is received on sfd,
+ * and connect the socket to the source addresse of the received message
+ * @sfd: a file descriptor to a bound socket but not yet connected
+ * @return: 0 in case of success, -1 otherwise
+ * @POST: This call is idempotent, it does not 'consume' the data of the message,
+ * and could be repeated several times blocking only at the first call.
+ */
+int wait_for_client(int sfd)
+{
+    int MAX_MESSAGE_SIZE = 1024;
+    uint8_t buff[MAX_MESSAGE_SIZE];   // allocate the receive buffer on the stack
+    struct sockaddr_storage peer_addr;  // allocate the peer's address on the stack. It will be initialized when we receive a message
+    socklen_t peer_addr_len = sizeof(struct sockaddr_storage); // variable that will contain the length of the peer's address
+    ssize_t amount_read = recvfrom(sfd, buff, MAX_MESSAGE_SIZE, MSG_PEEK, (struct sockaddr *) &peer_addr, &peer_addr_len);
+    if (amount_read == -1){ 
+        return -1;
+    }
+    int err             = connect(sfd, (struct sockaddr *) &peer_addr, sizeof(struct sockaddr_storage));
+    if (err != EISCONN && err != 0)
+        return -1;
+    return 0;
+}
+
+/*************************** End Q4 *******************************/
+
+int main(int argc, char const *argv[])
+{
+    if (argc != 4)
+    {
+        fprintf(stderr, "./get_ipv6_addr <name_to_resolve> <port> <flag>\n - <flag> ::= c `|` s\n");
+        return (EXIT_SUCCESS);
+    }     
+
+    // Name resolving
+    struct sockaddr_in6 * addr = (struct sockaddr_in6 *) malloc(sizeof(struct sockaddr_in6));
+    const char * res = real_address(argv[1], addr);
+    if (res != NULL)
+    {
+        fprintf(stderr, "An error occured when name resolving :\n\t%s\n", res);
+        return (EXIT_FAILURE);
+    } 
+    
+    // Socket Binding or Connecting
+    int socket;
+    if        (strncasecmp(argv[3], "c", 1) == 0)
+    {
+        socket = create_socket(NULL, 0, addr, atoi(argv[2]));
+    } else if (strncasecmp(argv[3], "s", 1) == 0)
+    {
+        socket = create_socket(addr, atoi(argv[2]), NULL, 0);
+        wait_for_client(socket);
+    }
+    if (socket == -1)
+    {
+        fprintf(stderr, "An error occured when connecting/binding to address\n");
+        return (EXIT_FAILURE);
+    }
+
+    read_write_loop(socket);
+
+    close(socket);
+    // Writing and reading
+    return (EXIT_SUCCESS    );
+}
\ No newline at end of file