Commit 92197fd3 authored by Naman Dixit's avatar Naman Dixit

Commiting v1 into the new repo

parent 124cdfe7
resource_manager/bin/**
[submodule "resource_manager/src/common/cJSON"]
path = resource_manager/src/common/cJSON
url = https://github.com/DaveGamble/cJSON
Dependency: Clang compiler
1. Clone using "git clone --recursive https://namandixit@git.cse.iitb.ac.in/namandixit/FaaS-Tactician.git"
2. Run "build.linux" script to compile the project.
#!/usr/bin/env bash
if [ -z ${BuildPlatform+x} ]; then
BuildPlatform=linux
fi
if [ -z ${BuildArchitecture+x} ]; then
BuildArchitecture=x64
fi
ProjectRoot="$( cd "$(dirname "$0")" ; pwd -P)" # Directory in which the script is located
cd ${ProjectRoot}
echo "Entering directory \`$(pwd)'"
BuildDirectory="bin/${BuildPlatform}/${BuildArchitecture}"
mkdir -p ${BuildDirectory}
VersionNumberOld=$(< ./version.linux)
VersionNumber=$((${VersionNumberOld} + 1))
echo ${VersionNumber} > ./version.linux
# .....................................................................
# BUILD
# `````````````````````````````````````````````````````````````````````
Compiler="clang"
# Compile Arbiter =====================================================
ArbiterSource=${ProjectRoot}/src/arbiter/arbiter.c
ArbiterTarget=arbiter
ArbiterTargetPath="bin/${BuildPlatform}/${BuildArchitecture}/${ArbiterTarget}"
if [ -f "${ArbiterTargetPath}" ]; then
rm "${ArbiterTargetPath}"
fi
# For Address Sanitizer: -fsanitize=address -fno-omit-frame-pointer
# Memory Sanitizer : -fsanitize=memory -fno-optimize-sibling-calls -fno-omit-frame-pointer -fsanitize-memory-track-origins
ArbiterCompilerFlags="-iquote /code/include -iquote ${ProjectRoot}/src \
-iquote ${ProjectRoot}/src/common \
-g3 -O0 -fno-strict-aliasing -fwrapv -msse2 \
"
ArbiterLanguageFlags="--std=c11 -DBUILD_INTERNAL -DBUILD_SLOW -DBUILD_DEBUG \
-DBUILD_NUMBER=${NEW_BUILD_NUMBER} \
-D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE"
ArbiterWarningFlags="-Weverything -Wpedantic -pedantic-errors -Werror \
-Wno-c++98-compat -Wno-gnu-statement-expression \
-Wno-bad-function-cast -Wno-unused-function \
-Wno-padded "
ArbiterLinkerFlags="-o ${ArbiterTargetPath} \
-static-libgcc -lm -pthread \
-Wl,-rpath=\${ORIGIN} -Wl,-z,origin -Wl,--enable-new-dtags"
${Compiler} ${ArbiterCompilerFlags} ${ArbiterLanguageFlags} ${ArbiterWarningFlags} \
${ArbiterSource} \
${ArbiterLinkerFlags}
# Compile Grunt =====================================================
GruntSource=${ProjectRoot}/src/grunt/grunt.c
GruntTarget=grunt
GruntTargetPath="bin/${BuildPlatform}/${BuildArchitecture}/${GruntTarget}"
if [ -f "${GruntTargetPath}" ]; then
rm "${GruntTargetPath}"
fi
# For Address Sanitizer: -fsanitize=address -fno-omit-frame-pointer
# Memory Sanitizer : -fsanitize=memory -fno-optimize-sibling-calls -fno-omit-frame-pointer -fsanitize-memory-track-origins
GruntCompilerFlags="-iquote /code/include -iquote ${ProjectRoot}/src \
-iquote ${ProjectRoot}/src/common \
-g3 -O0 -fno-strict-aliasing -fwrapv -msse2 \
"
GruntLanguageFlags="--std=c11 -DBUILD_INTERNAL -DBUILD_SLOW -DBUILD_DEBUG \
-DBUILD_NUMBER=${NEW_BUILD_NUMBER} \
-D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE"
GruntWarningFlags="-Weverything -Wpedantic -pedantic-errors -Werror \
-Wno-c++98-compat -Wno-gnu-statement-expression \
-Wno-bad-function-cast -Wno-unused-function \
-Wno-padded "
GruntLinkerFlags="-o ${GruntTargetPath} \
-static-libgcc -lm -pthread \
-Wl,-rpath=\${ORIGIN} -Wl,-z,origin -Wl,--enable-new-dtags"
${Compiler} ${GruntCompilerFlags} ${GruntLanguageFlags} ${GruntWarningFlags} \
${GruntSource} \
${GruntLinkerFlags}
# Compile Test =====================================================
TestSource=${ProjectRoot}/src/test/test.c
TestTarget=test
TestTargetPath="bin/${BuildPlatform}/${BuildArchitecture}/${TestTarget}"
if [ -f "${TestTargetPath}" ]; then
rm "${TestTargetPath}"
fi
# For Address Sanitizer: -fsanitize=address -fno-omit-frame-pointer
# Memory Sanitizer : -fsanitize=memory -fno-optimize-sibling-calls -fno-omit-frame-pointer -fsanitize-memory-track-origins
TestCompilerFlags="-iquote /code/include -iquote ${ProjectRoot}/src \
-iquote ${ProjectRoot}/src/common \
-g3 -O0 -fno-strict-aliasing -fwrapv -msse2 \
"
TestLanguageFlags="--std=c11 -DBUILD_INTERNAL -DBUILD_SLOW -DBUILD_DEBUG \
-DBUILD_NUMBER=${NEW_BUILD_NUMBER} \
-D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE"
TestWarningFlags="-Weverything -Wpedantic -pedantic-errors -Werror \
-Wno-c++98-compat -Wno-gnu-statement-expression \
-Wno-bad-function-cast -Wno-unused-function \
-Wno-padded "
TestLinkerFlags="-o ${TestTargetPath} \
-static-libgcc -lm -pthread \
-Wl,-rpath=\${ORIGIN} -Wl,-z,origin -Wl,--enable-new-dtags"
${Compiler} ${TestCompilerFlags} ${TestLanguageFlags} ${TestWarningFlags} \
${TestSource} \
${TestLinkerFlags}
This diff is collapsed.
/*
* Creator: Naman Dixit
* Notice: © Copyright 2020 Naman Dixit
*/
typedef enum Socket_Kind {
Socket_Kind_NONE,
Socket_Kind_INTERNAL,
Socket_Kind_EXTERNAL,
} Socket_Kind;
internal_function
Sint socketCreateListener (Char *port)
{
printf("Openiing socket on port %s\n", port);
// NOTE(naman): Create a socket for IPv4 and TCP.
Sint sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0) {
perror("ERROR opening socket");
exit(-1);
}
// NOTE(naman): This helps avoid spurious EADDRINUSE when the previous instance of this
// server died.
int opt = 1;
if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
perror("setsockopt");
exit(-1);
}
// NOTE(naman): Get actual internet address to bind to using IPv4 and TCP,
// and listening passively
struct addrinfo hints = {.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
.ai_flags = AI_PASSIVE};
struct addrinfo *addrinfo = NULL;
Sint s = getaddrinfo(NULL, port, &hints, &addrinfo);
if (s != 0) {
fprintf(stderr, "Error: getaddrinfo: %s\n", gai_strerror(s));
exit(-1);
}
// NOTE(naman): Assign an address to the socket
if (bind(sock_fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0) {
perror("bind()");
exit(-1);
}
// NOTE(naman): Start listening for incoming connections
if (listen(sock_fd, MAX_SOCKET_CONNECTIONS_REQUEST) != 0) {
perror("listen()");
exit(-1);
}
// NOTE(naman): Set the socket as non-blocking
int flags = fcntl(sock_fd, F_GETFL, 0);
if (flags == -1) {
perror("fcntl F_GETFL");
exit(-1);
}
if (fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK) == -1) {
perror("fcntl F_SETFL O_NONBLOCK");
exit(-1);
}
printf("Log: Waiting for connection on port %s...\n", port);
return sock_fd;
}
/*
* Creator: Naman Dixit
* Notice: © Copyright 2020 Naman Dixit
*/
internal_function
U64 timeMilli (void)
{
struct timespec now = {0};
U64 nanosec = 0;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &now) == 0) {
nanosec = ((U64)now.tv_sec * 1000000000ULL) + (U64)now.tv_nsec;
} else {
struct timeval now_low = {0};
gettimeofday(&now_low, NULL);
nanosec = ((U64)now_low.tv_sec * 1000000000ULL) + (U64)(now_low.tv_usec * 100);
}
U64 millisec = nanosec / 1000000ULL;
return millisec;
}
Subproject commit f790e17b6cecef030c4eda811149d238c2085fcf
This diff is collapsed.
/*
* Creator: Naman Dixit
* Notice: © Copyright 2019 Naman Dixit
*/
#if !defined(UNICODE_H_INCLUDE_GUARD)
header_function
B64 unicodeCodepointFromUTF16Surrogate (U16 surrogate, U16 *last_surrogate, U32 *codepoint)
{
U16 utf16_hi_surrogate_start = 0xD800;
U16 utf16_lo_surrogate_start = 0xDC00;
U16 utf16_surrogate_end = 0xDFFF;
if ((surrogate >= utf16_hi_surrogate_start) &&
(surrogate < utf16_lo_surrogate_start)) {
*last_surrogate = surrogate;
return false;
} else {
if ((surrogate >= utf16_lo_surrogate_start) &&
(surrogate <= utf16_surrogate_end)) {
U16 low_surrogate = surrogate;
// NOTE(naman): In this line, the numbers get promoted from U16 to S32,
// so storing them in a U32 results in a inmpicit sign conversion.
// That is why we are casting manually.
*codepoint = (U32)((*last_surrogate - utf16_hi_surrogate_start) << 10U);
*codepoint |= (low_surrogate - utf16_lo_surrogate_start);
*codepoint += 0x10000;
*last_surrogate = 0;
} else {
*codepoint = surrogate;
}
return true;
}
}
header_function
Size unicodeUTF8FromUTF32 (U32 *codepoints, Size codepoint_count, Char *buffer)
{
if (buffer == NULL) {
Size length = 1; // NOTE(naman): We need one byte for the NUL byte.
for (Size i = 0; i < codepoint_count; i++) {
if (codepoints[i] <= 0x7F) {
length += 1;
} else if (codepoints[i] <= 0x7FF) {
length += 2;
} else if (codepoints[i] <= 0xFFFF) {
length += 3;
} else if (codepoints[i] <= 0x10FFFF) {
length += 4;
}
}
return length;
} else {
Size length = 1; // NOTE(naman): We need one byte for the NUL byte.
for (Size i = 0; i < codepoint_count; i++) {
if (codepoints[i] <= 0x7F) {
buffer[0] = (Char)codepoints[i];
buffer += 1;
length += 1;
} else if (codepoints[i] <= 0x7FF) {
buffer[0] = (Char)(0xC0 | (codepoints[i] >> 6)); /* 110xxxxx */
buffer[1] = (Char)(0x80 | (codepoints[i] & 0x3F)); /* 10xxxxxx */
buffer += 2;
length += 2;
} else if (codepoints[i] <= 0xFFFF) {
buffer[0] = (Char)(0xE0 | (codepoints[i] >> 12)); /* 1110xxxx */
buffer[1] = (Char)(0x80 | ((codepoints[i] >> 6) & 0x3F)); /* 10xxxxxx */
buffer[2] = (Char)(0x80 | (codepoints[i] & 0x3F)); /* 10xxxxxx */
buffer += 3;
length += 3;
} else if (codepoints[i] <= 0x10FFFF) {
buffer[0] = (Char)(0xF0 | (codepoints[i] >> 18)); /* 11110xxx */
buffer[1] = (Char)(0x80 | ((codepoints[i] >> 12) & 0x3F)); /* 10xxxxxx */
buffer[2] = (Char)(0x80 | ((codepoints[i] >> 6) & 0x3F)); /* 10xxxxxx */
buffer[3] = (Char)(0x80 | (codepoints[i] & 0x3F)); /* 10xxxxxx */
buffer += 4;
length += 4;
}
}
buffer[0] = '\0';
return length;
}
}
# if defined(OS_WINDOWS)
header_function
LPWSTR unicodeWin32UTF16FromUTF8 (Char *utf8)
{
int wcstr_length = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
LPWSTR wcstr = VirtualAlloc(NULL, (DWORD)wcstr_length * sizeof(wchar_t),
MEM_COMMIT, PAGE_READWRITE);
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wcstr, wcstr_length);
int normalized_length = NormalizeString(NormalizationC,
wcstr, -1,
NULL, 0);
LPWSTR norm = VirtualAlloc(NULL, (DWORD)normalized_length * sizeof(wchar_t),
MEM_COMMIT, PAGE_READWRITE);
NormalizeString(NormalizationC, wcstr, -1, norm, normalized_length);
VirtualFree(wcstr, 0, MEM_RELEASE);
return norm;
}
header_function
void unicodeWin32UTF16Dealloc (LPWSTR utf16)
{
VirtualFree(utf16, 0, MEM_RELEASE);
}
# endif
#define UNICODE_H_INCLUDE_GUARD
#endif
/*
* Creator: Naman Dixit
* Notice: © Copyright 2020 Naman Dixit
*/
#include "nlib/nlib.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <sys/time.h>
#define MAX_EPOLL_EVENTS 1024
# if defined(COMPILER_CLANG)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
# pragma clang diagnostic ignored "-Wfloat-equal"
# endif
#include "cJSON/cJSON.h"
#include "cJSON/cJSON.c"
# if defined(COMPILER_CLANG)
# pragma clang diagnostic pop
# endif
typedef struct Command {
Sint id;
Sint dispatcher_socket;
Sint memory;
} Command;
#include "time.c"
#include"socket.c"
int main(int argc, char** argv)
{
unused_variable(argc);
unused_variable(argv);
Char *port = "9527";
Sint sock_fd = socket(AF_INET, SOCK_STREAM, 0);
struct addrinfo hints = {.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM};
struct addrinfo *result = NULL;
Sint s = getaddrinfo(NULL, port, &hints, &result);
if (s != 0) {
fprintf(stderr, "Error: getaddrinfo: %s\n", gai_strerror(s));
exit(-1);
}
// NOTE(naman): Create an epoll instance, with no flags set.
int epoll_fd = epoll_create1(0);
if (epoll_fd < 0) {
perror("epoll_create1");
exit(-1);
}
// NOTE(naman): Add the socket's file descriptor to the epoll set
struct epoll_event accept_event = {.data.fd = sock_fd,
.events = EPOLLIN};
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock_fd, &accept_event) < 0) {
perror("epoll_ctl EPOLL_CTL_ADD");
exit(-1);
}
// NOTE(naman): Allocate memory for epoll array
struct epoll_event* events = calloc(MAX_EPOLL_EVENTS, sizeof(struct epoll_event));
if (events == NULL) {
fprintf(stderr, "Unable to allocate memory for epoll_events");
exit(-1);
}
while (connect(sock_fd, result->ai_addr, result->ai_addrlen) == -1) {
fprintf(stderr, "Error: Couldn't connect on port %s, trying again in one second...\n", port);
sleep(1);
}
printf("Log: Starting communication with server on port %s...\n", port);
U64 time_begin = timeMilli();
U64 time_accum = 0;
while (true) {
// NOTE(naman): Get the fd's that are ready
int nready = epoll_wait(epoll_fd, events, MAX_EPOLL_EVENTS, 1000);
for (int i = 0; i < nready; i++) {
if (events[i].events & EPOLLERR) {
perror("epoll_wait returned EPOLLERR");
exit(-1);
}
if (events[i].events & EPOLLIN) {
B32 initialized = false;
Size buffer_len = 0;
Size buffer_cap = MiB(1);
U32 buffer_expected_len = 0;
Char *buffer = calloc(buffer_cap, sizeof(*buffer));
Char size_bytes[4] = {0};
Size size_bytes_count = 0;
Command *c = NULL;
while (true) {
if (initialized == false) {
long len = read(sock_fd,
(Char*)size_bytes + size_bytes_count,
4 - size_bytes_count);
if (len == 0) {
perror("read() returned zero");
exit(-1);
}
size_bytes_count += (Size)len;
if (size_bytes_count == 4) {
initialized = true;
buffer_expected_len = (U32)((size_bytes[3] << 0U) |
(size_bytes[2] << 8U) |
(size_bytes[1] << 16U) |
(size_bytes[0] << 24U));
}
continue;
} else {
long len = read(sock_fd,
buffer + buffer_len,
buffer_expected_len - buffer_len);
buffer_len += (Size)len;
if (buffer_expected_len == buffer_len) {
cJSON_Print(cJSON_Parse(buffer));
printf("%.*s", (int)buffer_len, buffer);
const Char *json_error = NULL;
cJSON *root = cJSON_ParseWithOpts(buffer, &json_error, true);
if (root == NULL) {
// TODO(naman): Error
} else {
c = calloc(1, sizeof(*c));
c->id = cJSON_GetObjectItem(root, "id")->valueint;
c->dispatcher_socket = cJSON_GetObjectItem(root, "dispatcher_socket")->valueint;
c->memory = cJSON_GetObjectItem(root, "memory")->valueint;
}
free(buffer);
break;
}
}
}
int memory = 0;
FILE *meminfo = fopen("/proc/meminfo", "r");
Char line[256] = {0};
while(fgets(line, sizeof(line), meminfo)) {
if (sscanf(line, "MemTotal: %d kB", &memory) == 1) {
fclose(meminfo);
break;
}
}
Char *output = NULL;
sbufPrint(output, " ");
sbufPrint(output, "{\n\"id\": %d", c->id);
sbufPrint(output, ",\n\"dispatcher_socket\": %d", c->dispatcher_socket);
sbufPrint(output, ",\n\"type\": \"response\"");
if (memory >= c->memory) {
sbufPrint(output, ",\n\"success\": %d\n", 1);
} else {
sbufPrint(output, ",\n\"success\": %d\n", 0);
}
sbufPrint(output, "\n}\n");
Size output_len = strlen(output);
#if defined(ENDIAN_LITTLE)
U32 json_len = (U32)output_len - 4;
U32 json_len_be = swap_endian(json_len);
output[0] = ((Char*)&json_len_be)[0];
output[1] = ((Char*)&json_len_be)[1];
output[2] = ((Char*)&json_len_be)[2];
output[3] = ((Char*)&json_len_be)[3];
#endif
socketWrite(output, output_len, sock_fd);
}
}
{ // Send a heartbeat message if it is time to do so
U64 time_new = timeMilli();
U64 time_passed = time_new - time_begin;
time_begin = time_new;
time_accum += time_passed;
if (time_accum >= 1000) {
time_accum = 0;
int memory = 0;
FILE *meminfo = fopen("/proc/meminfo", "r");
Char line[256] = {0};
while(fgets(line, sizeof(line), meminfo)) {
if (sscanf(line, "MemTotal: %d kB", &memory) == 1) {
fclose(meminfo);
break;
}
}
Char *output = NULL;
sbufPrint(output, " ");
sbufPrint(output, "{");
sbufPrint(output, " \n\"type\": \"heartbeat\"");
sbufPrint(output, ",\n\"memory\": %d", memory);
sbufPrint(output, "\n}\n");
Size output_len = strlen(output);
#if defined(ENDIAN_LITTLE)
U32 json_len = (U32)output_len - 4;
U32 json_len_be = swap_endian(json_len);
output[0] = ((Char*)&json_len_be)[0];
output[1] = ((Char*)&json_len_be)[1];
output[2] = ((Char*)&json_len_be)[2];
output[3] = ((Char*)&json_len_be)[3];
#endif
socketWrite(output, output_len, sock_fd);
}
}
}
}
/*
* Creator: Naman Dixit
* Notice: © Copyright 2020 Naman Dixit
*/
internal_function
void socketWrite (Char *output, Size output_len,
int sock_fd)
{
ssize_t nsent = 0;
Size output_cursor = 0;
while (true) {
nsent = write(sock_fd, output + output_cursor, output_len - output_cursor);
if (nsent == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
continue;
} else {
exit(-1);
}
} else if ((Size)nsent < output_len) {
output_cursor += (Size)nsent;
} else {
break;
}
}
}
/*
* Creator: Naman Dixit
* Notice: © Copyright 2020 Naman Dixit
*/
internal_function
U64 timeMilli (void)
{
struct timespec now = {0};
U64 nanosec = 0;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &now) == 0) {
nanosec = ((U64)now.tv_sec * 1000000000ULL) + (U64)now.tv_nsec;
} else {
struct timeval now_low = {0};
gettimeofday(&now_low, NULL);
nanosec = ((U64)now_low.tv_sec * 1000000000ULL) + (U64)(now_low.tv_usec * 100);
}
U64 millisec = nanosec / 1000000ULL;
return millisec;
}
/*
* Creator: Naman Dixit
* Notice: © Copyright 2020 Naman Dixit
*/
/*
* Creator: Naman Dixit
* Notice: © Copyright 2019 Naman Dixit
*/
#include "nlib/nlib.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <ctype.h>
# if defined(COMPILER_CLANG)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
# pragma clang diagnostic ignored "-Wfloat-equal"
# endif
#include "cJSON/cJSON.h"
#include "cJSON/cJSON.c"
# if defined(COMPILER_CLANG)
# pragma clang diagnostic pop
# endif
int main(int argc, char** argv)
{
if (argc < 2) {
printf("Error: Pass the amount of memory\n");
exit(-1);
}
Sint memory_required = (Sint)strtol(argv[1], NULL, 10);
Char *port = "9526";
Sint sock_fd = socket(AF_INET, SOCK_STREAM, 0);
struct addrinfo hints = {.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM};
struct addrinfo *result = NULL;
Sint s = getaddrinfo(NULL, port, &hints, &result);
if (s != 0) {
fprintf(stderr, "Error: getaddrinfo: %s\n", gai_strerror(s));
exit(-1);
}
while (connect(sock_fd, result->ai_addr, result->ai_addrlen) == -1) {
fprintf(stderr, "Error: Couldn't connect on port %s, trying again in one second...\n", port);
sleep(1);
}
printf("Log: Starting communication with server on port %s...\n", port);
Char *output = NULL;
sbufPrint(output, " ");
sbufPrint(output, "{\n\"id\": %d", (Sint)time(NULL));
sbufPrint(output, ",\n\"memory\": %d", memory_required);
sbufPrint(output, "\n}\n");
Size output_len = strlen(output);
printf("Sending to Arbiter:\n%s\n",
cJSON_Print(cJSON_Parse(output + 4)));
#if defined(ENDIAN_LITTLE)
U32 json_len = (U32)output_len - 4;
U32 json_len_be = swap_endian(json_len);
output[0] = ((Char*)&json_len_be)[0];
output[1] = ((Char*)&json_len_be)[1];
output[2] = ((Char*)&json_len_be)[2];
output[3] = ((Char*)&json_len_be)[3];
#endif
write(sock_fd, output, output_len);
{
cJSON *array = NULL;
B32 initialized = false;
Size buffer_len = 0;
Size buffer_cap = MiB(1);
U32 buffer_expected_len = 0;
Char *buffer = calloc(buffer_cap, sizeof(*buffer));
Char size_bytes[4] = {0};
Size size_bytes_count = 0;
while (true) {
if (initialized == false) {
long len = read(sock_fd,
(Char*)size_bytes + size_bytes_count,
4 - size_bytes_count);
if (len == 0) {
perror("read() returned zero");
exit(-1);
}
size_bytes_count += (Size)len;
if (size_bytes_count == 4) {
initialized = true;
buffer_expected_len = (U32)((size_bytes[3] << 0U) |
(size_bytes[2] << 8U) |
(size_bytes[1] << 16U) |
(size_bytes[0] << 24U));
}
continue;
} else {
long len = read(sock_fd,
buffer + buffer_len,
buffer_expected_len - buffer_len);
buffer_len += (Size)len;
if (buffer_expected_len == buffer_len) {
printf("Recieved: Final Response:\n%s\n",
cJSON_Print(cJSON_Parse(buffer)));
const Char *json_error = NULL;
cJSON *root = cJSON_ParseWithOpts(buffer, &json_error, true);
if (root == NULL) {
// TODO(naman): Error
} else {
array = cJSON_GetObjectItem(root, "ip");
}
free(buffer);
break;
}
}
}
}
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment