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 */