Browse Source

added simple socket server

master
Daniel Ledda 1 week ago
parent
commit
9b772e2046
5 changed files with 187 additions and 34 deletions
  1. +46
    -7
      app.c
  2. +11
    -13
      core.c
  3. +14
    -14
      core.h
  4. +40
    -0
      os.h
  5. +76
    -0
      os_linux.c

+ 46
- 7
app.c View File

@@ -1,13 +1,52 @@
#define DJSTD_BASIC_ENTRY

#include "core.c"
#include "signal.h"

Server *server = NULL;

void handleSigint(int dummy) {
if (server) {
print("\n");
print("Closing server socket.\n");
serverClose(server);
print("Success\n.");
}
exit(0);
}

int djstd_entry(Arena *arena, StringList args) {
signal(SIGINT, &handleSigint);

int port = 8080;
Int32Result portParsed = parsePositiveInt(args.data[0]);
if (portParsed.valid) {
port = portParsed.result;
}

print("Starting server on port %d\n", port);
Server myserver = serverInit((ServerInitInfo){
.concurrentClients=16,
.port=port,
.memory=Megabytes(64),
});

server = &myserver;

serverListen(&myserver);
Client *client = serverAccept(&myserver);

CharList buf = PushFullListZero(arena, CharList, 257);
uint64 bytesRead = clientRead(client, (void *)buf.data, buf.length - 1);

int main(int argc, char **argv) {
initialiseDjStdCore();
Arena *arena = arenaAlloc(Megabytes(64));
StringList args = getArgs(arena, argc, argv);
if (bytesRead > 0) {
print("Client said: %s\n", buf.data);
print("Now that's insightful.\n");
} else if (bytesRead == -1) {
print("Connection error\n");
}

print("Args:\n");
printStrList(args);
printStrList(strSplit(arena, s("-"), s("the-quick-brown-fox-jumps-over-the-lazy-dog")));
clientClose(client);

return 0;
}

+ 11
- 13
core.c View File

@@ -231,28 +231,27 @@ StringList strSplit(Arena *arena, string splitStr, string inputStr) {
return result;
}

ParsePositiveIntResult parsePositiveInt(string str, size_t *lengthPointer) {
Int32Result parsePositiveInt(string str) {
size_t numEnd = 0;
char currChar = str.str[numEnd];
while (numEnd < str.length && isNumeric(currChar)) {
currChar = str.str[++numEnd];
*lengthPointer += 1;
numEnd++;
currChar = str.str[numEnd];
}
*lengthPointer -= 1;
if (numEnd > 0) {
uint8 result = 0;
uint32 result = 0;
for (size_t i = 0; i < numEnd; i++) {
result *= 10;
result += str.str[i] - '0';
}
return (ParsePositiveIntResult){ .result=result, .valid=true };
return (Int32Result){ .result=result, .valid=true };
} else {
return (ParsePositiveIntResult){ .result=0, .valid=false};
return (Int32Result){ .result=0, .valid=false};
}
}

ParsePositiveReal32Result parsePositiveReal32(string str, size_t *lengthPointer) {
ParsePositiveReal32Result result = { .result=NAN, .valid=false};
Real32Result parsePositiveReal32(string str) {
Real32Result result = { .result=NAN, .valid=false};

string wholePartStr = (string){0};
string fractionalPartStr = (string){0};
@@ -271,9 +270,8 @@ ParsePositiveReal32Result parsePositiveReal32(string str, size_t *lengthPointer)
c++;
}
if (split) {
ParsePositiveIntResult wholePartParsed = parsePositiveInt(wholePartStr, lengthPointer);
*lengthPointer += 1;
ParsePositiveIntResult fractionalPartParsed = parsePositiveInt(fractionalPartStr, lengthPointer);
Int32Result wholePartParsed = parsePositiveInt(wholePartStr);
Int32Result fractionalPartParsed = parsePositiveInt(fractionalPartStr);
if (wholePartParsed.valid && fractionalPartParsed.valid) {
// TODO(dledda): implement powf with intrinsics? or just custom
real32 fractionalPartMultiplier = 1.0f / powf(10.0f, (real32)fractionalPartStr.length);
@@ -281,7 +279,7 @@ ParsePositiveReal32Result parsePositiveReal32(string str, size_t *lengthPointer)
result.valid = true;
}
} else if (c > 0) {
ParsePositiveIntResult intPartParsed = parsePositiveInt(str, lengthPointer);
Int32Result intPartParsed = parsePositiveInt(str);
if (intPartParsed.valid) {
result.result = (real32)intPartParsed.result;
result.valid = true;


+ 14
- 14
core.h View File

@@ -139,7 +139,7 @@ inline function Vec4 vec4(real32 x, real32 y, real32 z, real32 w) {
#define DefineList(type, prefix) \
typedef struct prefix ## List prefix ## List;\
struct prefix ## List {\
type* data;\
type *data;\
size_t length;\
size_t capacity;\
};\
@@ -211,19 +211,19 @@ StringList strSplit(Arena *arena, string splitStr, string inputStr);
string strPrintfv(Arena *arena, const char *fmt, va_list args);
string strPrintf(Arena *arena, const char *fmt, ...);

typedef struct ParsePositiveIntResult ParsePositiveIntResult;
struct ParsePositiveIntResult {
uint8 result;
bool valid;
};
ParsePositiveIntResult parsePositiveInt(string str, size_t *lengthPointer);
#define DefineResult(type, prefix) \
typedef struct prefix ## Result prefix ## Result;\
struct prefix ## Result {\
type result;\
bool valid;\
};\
typedef type prefix ## Result ## _underlying

typedef struct ParsePositiveReal32Result ParsePositiveReal32Result;
struct ParsePositiveReal32Result {
real32 result;
bool valid;
};
ParsePositiveReal32Result parsePositiveReal32(string str, size_t *lengthPointer);
DefineResult(int32, Int32);
Int32Result parsePositiveInt(string str);

DefineResult(real32, Real32);
Real32Result parsePositiveReal32(string str);

inline function bool isNumeric(char c);

@@ -304,7 +304,7 @@ extern void (*print)(const char *fmt, ...);

// ### Loops ###
#define EachIn(list, it) size_t it = 0; it < (list).length; it++
#define EachEl(list, type, element) type* element = (list).data; element < (list).data + (list).length; element += 1
#define EachEl(list, type, element) type *element = (list).data; element < (list).data + (list).length; element += 1
#define EachInReversed(list, it) size_t it = (list).length - 1; it >= 0 && it < (list).length; it--
#define EachInArray(arr, it) size_t it = 0; it < ArrayCount(arr); ++it



+ 40
- 0
os.h View File

@@ -25,4 +25,44 @@ struct OS_Thread {

OS_Thread os_createThread(void *(*entry)(void *ctx), void *ctx);

// ### Network I/O ###
typedef struct Address Address;
struct Address;

typedef struct Socket Socket;
struct Socket;

typedef struct Client Client;
struct Client {
Address *clientAddressData;
Socket *socket;
};
DefineList(Client, Client);

typedef struct Server Server;
struct Server {
Arena *arena;
Address *serverAddressData;
uint32 serverPort;
Socket *socket;
ClientList clients;
bool listening;
};

typedef struct ServerInitInfo ServerInitInfo;
struct ServerInitInfo {
uint16 port;
uint32 concurrentClients;
uint64 memory;
};

Server serverInit(ServerInitInfo info);
void serverListen(Server *s);
Client *serverAccept(Server *s);
void serverClose(Server *s);

uint64 clientRead(Client *client, void *dest, size_t bytes);
void clientWrite(Client *client);
void clientClose(Client *client);

#endif

+ 76
- 0
os_linux.c View File

@@ -9,6 +9,12 @@
#include "stdio.h"
#include "pthread.h"

#include "sys/socket.h"
#include "netinet/in.h"
#include "stdlib.h"
#include "arpa/inet.h"


void *os_alloc(size_t capacity) {
return mmap(0, capacity, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
}
@@ -106,4 +112,74 @@ OS_Thread os_createThread(void *(*entry)(void *), void *ctx) {
return (OS_Thread){ .id=handle };
}

Server serverInit(ServerInitInfo info) {
Arena *arena = arenaAlloc(info.memory);

struct sockaddr_in6 *serverAddr = PushStructZero(arena, struct sockaddr_in6);
serverAddr->sin6_family = AF_INET6;
serverAddr->sin6_port = htons(info.port);
serverAddr->sin6_addr = in6addr_loopback;

Server server = {
.arena=arena,
.serverAddressData=(Address *)serverAddr,
.clients=PushListZero(arena, ClientList, info.concurrentClients),
.listening=false,
.serverPort=info.port,
.socket=(Socket *)(uint64)socket(AF_INET6, SOCK_STREAM, 0 /* IPPROTO_TCP */),
};

int bindErr = bind((int)(uint64)server.socket, (struct sockaddr *)serverAddr, sizeof(*serverAddr));
if (bindErr == -1) {
// TODO(dledda): handle err
}

return server;
}

void serverListen(Server *s) {
int listenErr = listen((uint64)s->socket, s->clients.capacity);
if (listenErr == -1) {
// TODO(dledda): handle err
}
}

Client *serverAccept(Server *s) {
struct sockaddr_in6 *clientAddr = PushStructZero(s->arena, struct sockaddr_in6);
socklen_t clientAddrLen = sizeof(*clientAddr);

uint64 clientSock = accept((int)(uint64)s->socket, (struct sockaddr *)clientAddr, &clientAddrLen);
if (clientSock == -1) {
// TODO(dledda): handle err
}

if (s->clients.length < s->clients.capacity) {
AppendList(&s->clients, ((Client){
.socket=(Socket *)(uint64)clientSock,
.clientAddressData=(Address *)clientAddr,
}));
}

return &s->clients.data[s->clients.length - 1];
}

uint64 clientRead(Client *client, void *dest, size_t bytes) {
int bytesRead = read((uint64)client->socket, dest, bytes);
if (bytesRead == -1) {
// TODO(dledda): handle err
}
return bytesRead;
}

void clientWrite(Client *client) {
}

void clientClose(Client *client) {
close((int)(uint64)client->socket);
}

void serverClose(Server *s) {
close((int)(uint64)s->socket);
}

#endif

Loading…
Cancel
Save