diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..1aa601e7f92667314805137327237211aa6d1ea7
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,58 @@
+# You can use clang if you prefer
+CC = gcc
+
+# Feel free to add other C flags
+CFLAGS += -c -std=gnu99 -Wall -Werror -Wextra -O2
+# By default, we colorize the output, but this might be ugly in log files, so feel free to remove the following line.
+CFLAGS += -D_COLOR
+
+# You may want to add something here
+LDFLAGS +=
+
+# Adapt these as you want to fit with your project
+SENDER_SOURCES = $(wildcard src/sender.c src/log.c)
+RECEIVER_SOURCES = $(wildcard src/receiver.c src/log.c)
+
+SENDER_OBJECTS = $(SENDER_SOURCES:.c=.o)
+RECEIVER_OBJECTS = $(RECEIVER_SOURCES:.c=.o)
+
+SENDER = sender
+RECEIVER = receiver
+
+all: $(SENDER) $(RECEIVER)
+
+$(SENDER): $(SENDER_OBJECTS)
+	$(CC) $(SENDER_OBJECTS) -o $@ $(LDFLAGS)
+
+$(RECEIVER): $(RECEIVER_OBJECTS)
+	$(CC) $(RECEIVER_OBJECTS) -o $@ $(LDFLAGS)
+
+%.o: %.c
+	$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
+
+.PHONY: clean mrproper
+
+clean:
+	rm -f $(SENDER_OBJECTS) $(RECEIVER_OBJECTS)
+
+mrproper:
+	rm -f $(SENDER) $(RECEIVER)
+
+# It is likely that you will need to update this
+tests: all
+	./tests/run_tests.sh
+
+# By default, logs are disabled. But you can enable them with the debug target.
+debug: CFLAGS += -D_DEBUG
+debug: clean all
+
+# Place the zip in the parent repository of the project
+ZIP_NAME="../projet1_nom1_nom2.zip"
+
+# A zip target, to help you have a proper zip file. You probably need to adapt this code.
+zip:
+	# Generate the log file stat now. Try to keep the repository clean.
+	git log --stat > gitlog.stat
+	zip -r $(ZIP_NAME) Makefile README.md src tests rapport.pdf gitlog.stat
+	# We remove it now, but you can leave it if you want.
+	rm gitlog.stat
diff --git a/README.md b/README.md
index 1d2844da5210e027ff50350bbfcbf653c94dfd81..afcd6691d8f0f55fd60f8f1eeee85a3a922456e5 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,19 @@
-# project_TRTP
+# My Wonderful LINFO1341 Project
 
+The very first thing you might want to do in this folder is the following command:
+```bash
+git init
+```
+
+This will initialize your Git repository.
+You should also put it in a **private** repository (GitHub, GitLab, Bitbucket,... it is up to you but it **has to** stay private).
+
+The Makefile contains all the required targets, but you might want to extend their behavior.
+
+Very basic skelettons of receiver and sender source files are present, have a look to understand how you can enable logging or not.
+
+A very simple test case is present, you probably want to update it.
+
+You might be interested in the link simulator that can be found at https://github.com/cnp3/Linksimulator
+
+And finally, if this message is still there at your final submission, it looks like you forgot to provide a proper README.
\ No newline at end of file
diff --git a/src/log.c b/src/log.c
new file mode 100644
index 0000000000000000000000000000000000000000..25874a85e483f67b32d15a94547d30ba7ee6684a
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,21 @@
+/***
+ * A set of logging macro and functions that can be used.
+ */
+
+#include "log.h"
+
+/* Prints `len` bytes starting from `bytes` to stderr */
+void dump(const uint8_t *bytes, size_t len) {
+    for (size_t i = 0; i < len;) {
+        fprintf(stderr, "%04x:  ", (int) i);
+
+        for (size_t j = 0; j < 16 && i + j < len; j++) {
+            fprintf(stderr, "%02x ", bytes[i + j]);
+        }
+        fprintf(stderr, "\t");
+        for (size_t j = 0; j < 16 && i < len; j++, i++) {
+            fprintf(stderr,"%c ", bytes[i]);
+        }
+        fprintf(stderr,"\n");
+    }
+}
\ No newline at end of file
diff --git a/src/log.h b/src/log.h
new file mode 100644
index 0000000000000000000000000000000000000000..935275ff7a20fc8ef17cb1c10dac261b59686a7e
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,57 @@
+/***
+ * A set of logging macro and functions that can be used.
+ */
+
+#ifndef __LOG_H_
+#define __LOG_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef _COLOR
+/* Want more/other colors? See https://stackoverflow.com/a/3219471 and
+ * https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
+ */
+#define ANSI_COLOR_BRIGHT_RED "\x1b[91m"
+#define ANSI_COLOR_CYAN "\x1b[36m"
+#define ANSI_COLOR_RESET "\x1b[0m"
+#else
+#define ANSI_COLOR_BRIGHT_RED
+#define ANSI_COLOR_CYAN
+#define ANSI_COLOR_RESET
+#endif
+
+#define _LOG(color, prefix, msg, ...)\
+    do {\
+        fprintf(stderr, color prefix msg ANSI_COLOR_RESET "\n", ##__VA_ARGS__);\
+    } while (0)
+
+#define ERROR(msg, ...) _LOG(ANSI_COLOR_BRIGHT_RED, "[ERROR] ", msg, ##__VA_ARGS__)
+
+#ifdef _DEBUG
+#define DEBUG(msg, ...) _LOG(ANSI_COLOR_CYAN, "[DEBUG] ", msg, ##__VA_ARGS__)
+#else
+#define DEBUG(msg, ...)
+#endif
+
+/* Displays an error if `cond` is not true */
+/* Maybe it could also stop the program ? */
+#define ASSERT(cond) if (!(cond)) { ERROR("Assertion \"%s\" failed at %s:%d", #cond, __FILE__, __LINE__); }
+
+/* Prints `len` bytes starting from `bytes` to stderr */
+void dump(const uint8_t *bytes, size_t len);
+
+/* Use this useful macro instead of the bare function*/
+#ifdef _DEBUG
+#define DEBUG_DUMP(bytes, len) \
+    do {                       \
+        DEBUG("Dumping %ld bytes from pointer %p at %s:%d", (size_t) len, bytes, __FILE__, __LINE__); \
+        dump((const uint8_t *) bytes, (size_t) len); \
+    } while (0)
+#else
+#define DEBUG_DUMP(bytes, len)
+#endif
+
+#endif // __LOG_H_
\ No newline at end of file
diff --git a/src/receiver.c b/src/receiver.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b2c9aeb859e08d222937c1fcd863a343a3b4d79
--- /dev/null
+++ b/src/receiver.c
@@ -0,0 +1,58 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include "log.h"
+
+int print_usage(char *prog_name) {
+    ERROR("Usage:\n\t%s [-s stats_filename] listen_ip listen_port", prog_name);
+    return EXIT_FAILURE;
+}
+
+
+int main(int argc, char **argv) {
+    int opt;
+
+    char *stats_filename = NULL;
+    char *listen_ip = NULL;
+    char *listen_port_err;
+    uint16_t listen_port;
+
+    while ((opt = getopt(argc, argv, "s:h")) != -1) {
+        switch (opt) {
+        case 'h':
+            return print_usage(argv[0]);
+        case 's':
+            stats_filename = optarg;
+            break;
+        default:
+            return print_usage(argv[0]);
+        }
+    }
+
+    if (optind + 2 != argc) {
+        ERROR("Unexpected number of positional arguments");
+        return print_usage(argv[0]);
+    }
+
+    listen_ip = argv[optind];
+    listen_port = (uint16_t) strtol(argv[optind + 1], &listen_port_err, 10);
+    if (*listen_port_err != '\0') {
+        ERROR("Receiver port parameter is not a number");
+        return print_usage(argv[0]);
+    }
+
+    ASSERT(1 == 1); // Try to change it to see what happens when it fails
+    DEBUG_DUMP("Some bytes", 11); // You can use it with any pointer type
+
+    // This is not an error per-se.
+    ERROR("Receiver has following arguments: stats_filename is %s, listen_ip is %s, listen_port is %u",
+        stats_filename, listen_ip, listen_port);
+
+    DEBUG("You can only see me if %s", "you built me using `make debug`");
+    ERROR("This is not an error, %s", "now let's code!");
+
+    // Now let's code!
+    return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/src/sender.c b/src/sender.c
new file mode 100644
index 0000000000000000000000000000000000000000..db31cc8e9d2b9cbfaeeba0851c29aefe35dedd59
--- /dev/null
+++ b/src/sender.c
@@ -0,0 +1,67 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include "log.h"
+
+int print_usage(char *prog_name) {
+    ERROR("Usage:\n\t%s [-f filename] [-s stats_filename] [-c] receiver_ip receiver_port", prog_name);
+    return EXIT_FAILURE;
+}
+
+
+int main(int argc, char **argv) {
+    int opt;
+
+    char *filename = NULL;
+    char *stats_filename = NULL;
+    char *receiver_ip = NULL;
+    char *receiver_port_err;
+    bool fec_enabled = false;
+    uint16_t receiver_port;
+
+    while ((opt = getopt(argc, argv, "f:s:hc")) != -1) {
+        switch (opt) {
+        case 'f':
+            filename = optarg;
+            break;
+        case 'h':
+            return print_usage(argv[0]);
+        case 's':
+            stats_filename = optarg;
+            break;
+	case 'c':
+	    fec_enabled = true;
+	    break;
+        default:
+            return print_usage(argv[0]);
+        }
+    }
+
+    if (optind + 2 != argc) {
+        ERROR("Unexpected number of positional arguments");
+        return print_usage(argv[0]);
+    }
+
+    receiver_ip = argv[optind];
+    receiver_port = (uint16_t) strtol(argv[optind + 1], &receiver_port_err, 10);
+    if (*receiver_port_err != '\0') {
+        ERROR("Receiver port parameter is not a number");
+        return print_usage(argv[0]);
+    }
+
+    ASSERT(1 == 1); // Try to change it to see what happens when it fails
+    DEBUG_DUMP("Some bytes", 11); // You can use it with any pointer type
+
+    // This is not an error per-se.
+    ERROR("Sender has following arguments: filename is %s, stats_filename is %s, fec_enabled is %d, receiver_ip is %s, receiver_port is %u",
+        filename, stats_filename, fec_enabled, receiver_ip, receiver_port);
+
+    DEBUG("You can only see me if %s", "you built me using `make debug`");
+    ERROR("This is not an error, %s", "now let's code!");
+
+    // Now let's code!
+    return EXIT_SUCCESS;
+}
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
new file mode 100755
index 0000000000000000000000000000000000000000..91f236b3e0597d0fbf25b24719d9682fdb754756
--- /dev/null
+++ b/tests/run_tests.sh
@@ -0,0 +1,6 @@
+# Note that this assumes to be called from the Makefile, you may want to adapt it.
+@echo "A very simple test"
+./tests/simple_test.sh
+# Run the same test, but this time with valgrind
+@echo "A very simple test, with Valgrind"
+VALGRIND=1 ./tests/simple_test.sh
\ No newline at end of file
diff --git a/tests/simple_test.sh b/tests/simple_test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..58a3a1a1431524bd0655c3c671714ed7c9496fd3
--- /dev/null
+++ b/tests/simple_test.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+# cleanup d'un test précédent
+rm -f received_file input_file
+
+# Fichier au contenu aléatoire de 512 octets
+dd if=/dev/urandom of=input_file bs=1 count=512 &> /dev/null
+
+valgrind_sender=""
+valgrind_receiver=""
+if [ ! -z "$VALGRIND" ] ; then
+    valgrind_sender="valgrind --leak-check=full --log-file=valgrind_sender.log"
+    valgrind_receiver="valgrind --leak-check=full --log-file=valgrind_receiver.log"
+fi
+
+# On lance le receiver et capture sa sortie standard
+$valgrind ./receiver -f received_file :: 2456  2> receiver.log &
+receiver_pid=$!
+
+cleanup()
+{
+    kill -9 $receiver_pid
+    kill -9 $link_pid
+    exit 0
+}
+trap cleanup SIGINT  # Kill les process en arrière plan en cas de ^-C
+
+# On démarre le transfert
+if ! $valgrind ./sender ::1 1341 < input_file 2> sender.log ; then
+  echo "Crash du sender!"
+  cat sender.log
+  err=1  # On enregistre l'erreur
+fi
+
+sleep 5 # On attend 5 seconde que le receiver finisse
+
+if kill -0 $receiver_pid &> /dev/null ; then
+  echo "Le receiver ne s'est pas arreté à la fin du transfert!"
+  kill -9 $receiver_pid
+  err=1
+else  # On teste la valeur de retour du receiver
+  if ! wait $receiver_pid ; then
+    echo "Crash du receiver!"
+    cat receiver.log
+    err=1
+  fi
+fi
+
+# On vérifie que le transfert s'est bien déroulé
+if [[ "$(md5sum input_file | awk '{print $1}')" != "$(md5sum received_file | awk '{print $1}')" ]]; then
+  echo "Le transfert a corrompu le fichier!"
+  echo "Diff binaire des deux fichiers: (attendu vs produit)"
+  diff -C 9 <(od -Ax -t x1z input_file) <(od -Ax -t x1z received_file)
+  exit 1
+else
+  echo "Le transfert est réussi!"
+  exit ${err:-0}  # En cas d'erreurs avant, on renvoie le code d'erreur
+fi
\ No newline at end of file