Threads and Scheduling
at main 124 lines 3.7 kB view raw
1#include "lib.h" 2#include "log.h" 3#include <stdlib.h> 4 5// Allocates new memory from src and returns a buffer to that memory. The user 6// must free that memory. 7Buffer bufcpy(Buffer src) { 8 Byte* buf = (Byte*)malloc(src.len * sizeof(Byte)); 9 exists(buf); 10 memcpy(buf, src.buf, src.len); 11 return (Buffer){ 12 .buf = buf, 13 .len = src.len, 14 }; 15} 16 17// Checks whether the buffer contains a valid string and that the size provided 18// matches the size of that string. 19Buffer validate_str(Buffer str, size_t max_len) { 20 size_t calculated_len = safe_strlen((const char*)str.buf, max_len); 21 if (str.len != calculated_len) { 22 log(ERROR, "%s:%d String's length (%zu) is not equal to given length (%zu).", __FILE__, __LINE__, calculated_len, str.len); 23 24 printf("\nBuffer contains: "); 25 for (size_t i = 0; i < max_len; ++i) printf("[%d] ", str.buf[i]); 26 printf("\n"); 27 28 exit(1); 29 } 30 if (str.len > max_len) { 31 log(ERROR, "%s:%d String's length (%zu) is larger than the buffer that contains it (%zu).\n", str.len, calculated_len); 32 33 printf("\nBuffer contains: "); 34 for (size_t i = 0; i < max_len; ++i) printf("[%d] ", str.buf[i]); 35 printf("\n"); 36 37 exit(1); 38 } 39 return str; 40} 41 42// Converts the buffer received from a socket into an array of processes. The 43// user must free this memory. 44Procs deserialize(Buffer out_buf, size_t msg_len) { 45 Procs procs = { 46 .procs = (Proc*)calloc(1, sizeof(Proc)), 47 .len = 1, 48 }; 49 exists(procs.procs); 50 51 // This loop will continue until all Proc's have been deserialized. 52 size_t buf_idx = 0; 53 for (size_t j = 0; buf_idx < msg_len; ++j) { 54 // Reallocate new Proc if more than one proc was received. 55 if (j == procs.len) { 56 procs.procs = (Proc*)realloc(procs.procs, procs.len + 1); 57 procs.len = procs.len + 1; 58 } 59 60 // curr represents the first byte where the Proc lives in the message. 61 Byte* curr = out_buf.buf + buf_idx; 62 63 // Parse out the data members. 64 Time time = *(Time*)curr; 65 size_t len = *(size_t*)(curr + sizeof(Time)); 66 Byte* str_buf = curr + sizeof(Time) + sizeof(size_t); 67 68 // Validate the string in the buffer. 69 Buffer program = validate_str((Buffer){.len = len, .buf = str_buf}, msg_len - buf_idx); 70 71 // Insert everything into the proc list. 72 procs.procs[j] = (Proc){ 73 .time = time, 74 .program = bufcpy(program), 75 }; 76 77 // This calculates where the next Proc will be. 78 buf_idx += sizeof(Time) + sizeof(size_t) + program.len + 1; 79 } 80 return procs; 81} 82 83// This function turns a proc into a buffer. In order to do that, this function 84// reinterprets everything on the proc as a sequence of bytes. 85Buffer serialize(Proc proc) { 86 // First, determine how long the buffer has to be. 87 size_t len = sizeof(Time) + sizeof(size_t) + proc.program.len + 1; 88 89 // Allocate the bytes in the buffer. 90 Buffer buf = { 91 .len = len, 92 .buf = (Byte*)calloc(len, sizeof(Byte)), 93 }; 94 exists(buf.buf); 95 96 // Copy everything in the buffer. 97 memcpy((void*)buf.buf, (void*)&proc.time, sizeof(Time)); 98 memcpy((void*)(buf.buf + sizeof(Time)), (void*)&proc.program.len, sizeof(size_t)); 99 memcpy((void*)(buf.buf + sizeof(Time) + sizeof(size_t)), (void*)proc.program.buf, proc.program.len); 100 return buf; 101} 102 103// This function takes a string representing an IPv4 address and converts it 104// into an IPv4 type. 105IPv4 parse_address(const char* str) { 106 size_t len = safe_strlen(str, 15); 107 108 IPv4 ip = {0}; 109 size_t curr_byte = 0; 110 for (size_t i = 0; i < len; ++i) { 111 if (str[i] == '.') { 112 ++curr_byte; 113 } else { 114 ip.bytes[curr_byte] = (Byte)(ip.bytes[curr_byte] * 10 + (str[i] - '0')); 115 } 116 } 117 118 return ip; 119} 120 121// uses memchr to calculate strlen. 122size_t safe_strlen(const char* str, size_t max_len) { 123 return (size_t)memchr(str, '\0', max_len) - (size_t)str; 124}