diff --git a/common/link_emulator/link b/common/link_emulator/link
new file mode 100755
index 0000000000000000000000000000000000000000..84cca1b8ed57ab973d6eeb5bcc1cd92ed980a4e4
Binary files /dev/null and b/common/link_emulator/link differ
diff --git a/lab2/common.h b/lab2/common.h
index 94b55bdd1aa83d2f630b3b47fdbcd84549fd0fc5..53e8c5c0a1575eda58e2daf339f803428ec78ec4 100644
--- a/lab2/common.h
+++ b/lab2/common.h
@@ -6,8 +6,8 @@
 /* DELIM | DATE | DELIM */
 struct __attribute__((packed)) Frame {
     char frame_delim_start[2]; /* DLE STX */
-
-    /* TODO 2: Add source and destination */
+    int source;
+    int dest;
     char payload[30];  /* Datele pe care vrem sa le transmitem */
     char frame_delim_end[2]; /* DLE ETX */
 };
diff --git a/lab2/recv.c b/lab2/recv.c
index 3e6d72d6da2f7223ea8e616d2a54b039c27af001..041fb5851f89cea6df6a991e3a67df0965e6e270 100644
--- a/lab2/recv.c
+++ b/lab2/recv.c
@@ -16,68 +16,83 @@
 #define PORT 10001
 
 #include "common.h"
+#define BUFFER_SIZE 32
 
 /* Our unique layer 2 ID */
 static int ID = 123131;
 
+int recv_bytes(char *buffer, int length) {
+    int i = 0;
+    while (i < length) {
+        char c = recv_byte();
+        if (c == DLE) {
+            char next = recv_byte();
+            if (next == DLE) {
+                buffer[i++] = DLE;
+            } else {
+                return -1;
+            }
+        } else {
+            buffer[i++] = c;
+        }
+    }
+    return i; 
+}
+
 /* Function which our protocol implementation will provide to the upper layer. */
 int recv_frame(char *buf, int size)
 {
-	/* TODO 1.1: Call recv_byte() until we receive the frame start
-	 * delimitator. This operation makes this function blocking until it
-	 * receives a frame. */
-
-	/* TODO 2.1: The first two 2 * sizeof(int) bytes represent sender and receiver ID */
-
-	/* TODO 2.2: Check that the frame was sent to me */
-
-	/* TODO 1.2: Read bytes and copy them to buff until we receive the end of the frame */
+	char frame;
+	char frame2;
+
+	fprintf(stderr, "1\n");
+	frame = recv_byte();
+	fprintf(stderr, "2\n");
+	frame2 = recv_byte();
+	fprintf(stderr, "3\n");
+
+	while( ((frame != DLE) && (frame2 != STX)) || (frame == DLE && frame2 != STX)
+        || (frame != DLE && frame2 == STX)) {
+		frame = frame2;
+		frame2 = recv_byte();
+	}
 
-	/* If everything went well return the number of bytes received */
-	return 0;
+	int source;
+	int dest;
+	(void) source;
+	recv_bytes((char *)&source, sizeof(int));
+    recv_bytes((char *)&dest, sizeof(int));
+	if (dest != ID) {
+        fprintf(stderr, "skipping\n");
+        return -1;
+    }
+
+	int i;
+	for (i = 0; i < size; i++) {
+		char byte = recv_byte();
+		if (byte == DLE) {
+			char next = recv_byte();
+			if (next == ETX) {
+				buf[i] = '\0';
+				break;
+			} else if (next == DLE) {
+				buf[i] = DLE;
+			} else {
+				return -1;
+			}
+		} else {
+			buf[i] = byte;
+		}
+	}
+	return i;
 }
 
 int main(int argc,char** argv){
-	/* Don't modify this */
 	init(HOST,PORT);
 
-        // TODO remove these recives, whih are hardcoded to receive a "Hello"
-	// message, and replace them with code that can receive any message.
-	char c;
-
-	/* Wait for the start of a frame */
-	char c1,c2;
-	c1 = recv_byte();
-	c2 = recv_byte();
-
-	/* Cat timp nu am primit DLE STX citim bytes */
-	while((c1 != DLE) && (c2 != STX)) {
-		c1 = c2;
-		c2 = recv_byte();
-	}
-
-
-	printf("%d ## %d\n",c1, c2);
-	c = recv_byte();
-	printf("%c\n", c);
-
-	c = recv_byte();
-	printf("%c\n", c);
-
-	c = recv_byte();
-	printf("%c\n", c);
-
-	c = recv_byte();
-	printf("%c\n", c);
-
-	c = recv_byte();
-	printf("%c\n", c);
-
-	c = recv_byte();
-	printf("%c\n", c);
-
-	/* TODO 1.0: Allocate a buffer and call recv_frame */
-
+	char buffer[BUFFER_SIZE];
+	recv_frame(buffer, BUFFER_SIZE);
+	printf("%s\n", buffer);
 
 	/* TODO 3: Measure latency in a while loop for any frame that contains
 	 * a timestamp we receive, print frame_size and latency */
diff --git a/lab2/send.c b/lab2/send.c
index 7e70a31960580501367f020bb8f9bf8eded35f11..e817e304454e611d64d55cd89e7973f76fd2df0b 100644
--- a/lab2/send.c
+++ b/lab2/send.c
@@ -22,21 +22,38 @@
 
 /* Our unqiue layer 2 ID */
 static int ID = 123131;
+#define BUFFER_SIZE 32
 
 /* Function which our protocol implementation will provide to the upper layer. */
 int send_frame(char *buf, int size)
 {
 
 	/* TODO 1.1: Create a new frame. */
-
+	struct Frame *new_frame = (struct Frame *)malloc(sizeof(struct Frame));
+	new_frame->frame_delim_start[0] = DLE;
+	new_frame->frame_delim_start[1] = STX;
 	/* TODO 1.2: Copy the data from buffer to our frame structure */
-
-	/* TODO 2.1: Set the destination and source */
-
-	/* TODO 1.3: We can cast the frame to a char *, and iterate through sizeof(struct Frame) bytes
-	 calling send_bytes. */
-
-	/* if all went all right, return 0 */
+	if (size > sizeof(new_frame->payload)) {
+        fprintf(stderr, "buffer size exceeds payload size\n");
+        free(new_frame);
+        return -1;
+    }
+	memcpy(new_frame->payload, buf, size);
+	new_frame->frame_delim_end[0] = DLE;
+	new_frame->frame_delim_end[1] = ETX;	
+	
+	new_frame->source = ID;
+	new_frame->dest = ID;
+
+	char *frame = (char *)new_frame;
+	int size_of_frame = sizeof(struct Frame);
+	for (int i = 0; i < size_of_frame; i++) {
+		if (frame[i] == DLE) {
+			send_byte(DLE);
+		}
+		send_byte(frame[i]);
+	}
+	free(new_frame);
 	return 0;
 }
 
@@ -44,22 +61,10 @@ int main(int argc,char** argv){
 	// Don't touch this
 	init(HOST,PORT);
 
-	// TODO remove these sends, whih are hardcoded to send a "Hello"
-	// message, and replace them with code that can send any message.
-	/* Send Hello */
-	send_byte(DLE);
-	send_byte(STX);
-	send_byte('H');
-	send_byte('e');
-	send_byte('l');
-	send_byte('l');
-	send_byte('o');
-	send_byte('!');
-	send_byte(DLE);
-	send_byte(ETX);
-
-	/* TODO 1.0: Get some input in a buffer and call send_frame with it */
-
+	char buffer[BUFFER_SIZE];
+	fgets(buffer, BUFFER_SIZE, stdin);
+	int length = strlen(buffer);
+	send_frame(buffer, length - 1);
 	/* TODO 3.1: Get a timestamp of the current time copy it in the the payload */
 
 	/* TODO 3.0: Update the maximum size of the payload in Frame to 100 (in common.h), send the frame */
diff --git a/lab3/common.c b/lab3/common.c
index 6ace0f1c93d6969eb859fcb495c98a2e2c828985..81fe35cdd3b5d99a2884af7d4367d2230fe54864 100644
--- a/lab3/common.c
+++ b/lab3/common.c
@@ -1,26 +1,33 @@
 #include "common.h"
+#include <arpa/inet.h>
 
 uint8_t simple_csum(uint8_t *buf, size_t len) {
 
 	/* TODO 1.1: Implement the simple checksum algorithm */
 	uint8_t sum = 0;
-
-	for (int i = 0; i < len; i++) {
+	
+	for (size_t i = 0; i < len; i++) {
 		sum += buf[i];
 	}
-
 	return sum;
 }
 
 uint32_t crc32(uint8_t *buf, size_t len)
 {
 	/* TODO 2.1: Implement the CRC 32 algorithm */
+	uint32_t crc = ~0;
+	const uint32_t POLY = 0xEDB88320;
 
-	/* Iterate through each byte of buff */
-	
-		/* Iterate through each bit */
-		/* If the bit is 1, compute the new reminder */
-
-	/* By convention, we negate the crc */
-	return 0;
+	for (size_t i = 0; i < len; i++) {
+		crc = crc ^ buf[i];
+		for (size_t j = 0; j < 8; j++) {
+			if (crc & 1) {
+				crc = (crc >> 1) ^ POLY;
+			} else {
+				crc = (crc >> 1);
+			}
+		}
+	}
+	crc = ~crc;
+	return crc;
 }
diff --git a/lab3/link_emulator.err b/lab3/link_emulator.err
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/lab3/link_emulator.out b/lab3/link_emulator.out
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/lab3/recv.c b/lab3/recv.c
index 84f3e99bfe2aa8d2f7399955da3d1cbb810a49d9..7be817aa9e6dedea8bbaa9e99fd3d790cce0c8d0 100644
--- a/lab3/recv.c
+++ b/lab3/recv.c
@@ -7,6 +7,7 @@
 #include "common.h"
 #include "link_emulator/lib.h"
 #include "include/utils.h"
+#include <inttypes.h>
 
 /**
  * You can change these to communicate with another colleague.
@@ -27,21 +28,41 @@ int main(int argc,char** argv) {
 	/* Receive the frame from the link */
 	int len = link_recv(&t, sizeof(struct l3_msg));
 	DIE(len < 0, "Receive message");
-
 	/* We have to convert it to host order */
+	uint32_t temp = t.hdr.sum;
 	uint32_t recv_sum = ntohl(t.hdr.sum);
-	t.hdr.sum = 0;
-	int sum_ok = (simple_csum((void *) &t, sizeof(struct l3_msg)) == recv_sum);
+	//int sum_ok = (simple_csum((void *) &t, sizeof(struct l3_msg)) == recv_sum);
 	/* TODO 2: Change to crc32 */
-
+	t.hdr.sum = 0;
+	int ok_sum = (crc32((uint8_t *) &t, sizeof(struct l3_msg)) == recv_sum);
 	/* Since we are sending messages with a payload of 1500 - sizeof(header), most of the times the bytes from
 	 * 30 - 1500 will be corrupted and thus when we are printing or string message "Hello world" we see no probems.
 	 * This will be visible when we will be sending a file */
 
-	printf("[RECV] len=%d; sum(%s)=0x%04hx; payload=\"%s\";\n", t.hdr.len, sum_ok ? "GOOD" : "BAD", recv_sum, t.payload);
+	printf("[RECV] len=%d; sum(%s)=0x%04x; payload=\"%s\";\n", t.hdr.len, ok_sum ? "GOOD" : "BAD", recv_sum, t.payload);
 
 	/* TODO 3.1: In a loop, recv a frame and check if the CRC is good */
+	while (true) {
+		link_recv(&t, sizeof(struct l3_msg));
+		uint32_t recieved_sum = ntohl(t.hdr.sum);
+		t.hdr.sum = 0;
+		int sum_good = (crc32((uint8_t *) &t, sizeof(struct l3_msg)) == recieved_sum);
+		if (!sum_good) {
+			struct l3_msg nack_msg;
+			memset(&nack_msg, 0, sizeof(struct l3_msg));
+			strcpy(nack_msg.payload, "NACK");
+			nack_msg.hdr.len = strlen(nack_msg.payload);
+			nack_msg.hdr.sum = htonl(crc32((uint8_t *)&nack_msg, sizeof(struct l3_msg)));
+			link_send(&nack_msg, sizeof(struct l3_msg));
+		} else {
+			printf("[RECV] len=%d; sum(%s)=0x%04hx; payload=\"%s\";\n", t.hdr.len, sum_good ? "GOOD" : "BAD", recieved_sum, t.payload);
+			FILE *file = fopen("recv.data", "a");
+			DIE(file == NULL, "Failed to open recv.data");
 
+			fwrite(t.payload, 1, t.hdr.len, file);
+			fclose(file);
+		}
+	}
 	/* TODO 3.2: If the crc is bad, send a NACK frame */
 
 	/* TODO 3.2: Otherwise, write the frame payload to a file recv.data */
diff --git a/lab3/send.c b/lab3/send.c
index c9f4e5b203d9838cf1b06a7e09ff81187bded35a..dd7c8d76d969240c0d92ad81e8e0dc83bb461092 100644
--- a/lab3/send.c
+++ b/lab3/send.c
@@ -30,17 +30,40 @@ int main(int argc,char** argv) {
 	t.hdr.sum = 0;
 
 	/* Since sum is on 32 bits, we have to convert it to network order */
-	t.hdr.sum = htonl(simple_csum((void *) &t, sizeof(struct l3_msg)));
-
+	//t.hdr.sum = htonl(simple_csum((void *) &t, sizeof(struct l3_msg)));
+	uint32_t temp = crc32((uint8_t *) &t, sizeof(struct l3_msg));
+	printf("[SEND] len=%d; sum=0x%04x; payload=\"%s\";\n", t.hdr.len, temp, t.payload);
 	/* TODO 2.0: Call crc32 function */
-
+	t.hdr.sum = htonl(temp);
+	
 	/* Send the message */
 	link_send(&t, sizeof(struct l3_msg));
 
 	/* TODO 3.1: Receive the confirmation */
-
 	/* TODO 3.2: If we received a NACK, retransmit the previous frame */
+	struct l3_msg recv;
+	link_recv(&recv, sizeof(struct l3_msg));
+	while (strcmp(recv.payload, "NACK") == 0) {
+		link_send(&t, sizeof(struct l3_msg));
+		link_recv(&recv, sizeof(struct l3_msg));
+	}
+	
+	FILE *f;
+	f = fopen("input.txt", "rb");
+	size_t bytes_read;
+	while ((bytes_read = fread(t.payload, 1, 1500, f)) > 0) {
+		t.hdr.len = bytes_read;
+		t.hdr.sum = 0;
+		t.hdr.sum = htonl(crc32((uint8_t *) &t, sizeof(struct l3_msg)));
+		link_send(&t, sizeof(struct l3_msg));
+		link_recv(&recv, sizeof(struct l3_msg));
+		while (strcmp(recv.payload, "NACK") == 0) {
+			link_send(&t, sizeof(struct l3_msg));
+			link_recv(&recv, sizeof(struct l3_msg));
+		}
 
+	}
+	fclose(f);
 	/* TODO 3.3: Update this to read the content of a file and send it as
 	 * chunks of that file given a MTU of 1500 bytes */