Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ CC=gcc
.PHONY: all
all: server


server: buffer.o connection.o net.o canvas.o main.o
$(CC) -o $@ $^ `sdl2-config --libs` -lpthread
$(CC) -o $@ $^ `sdl2-config --libs` -lpthread -lSDL2_ttf

%.o: %.c common.h buffer.h connection.h canvas.h net.h
$(CC) -Wall -Wextra -O -c -g `sdl2-config --cflags` -o $@ $<

.PHONY: clean
clean:
rm -f buffer.o connection.o main.o canvas.o net.o server
rm -f buffer.o connection.o main.o canvas.o text.o net.o server
143 changes: 143 additions & 0 deletions canvas.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
#include "SDL.h"
#include "SDL2/SDL_ttf.h"

#include "common.h"
#include "canvas.h"
#include "connection.h"

#define TEX_SIZE_X 512
#define TEX_SIZE_Y 512
#define SCREEN_SIZE_X 1024
#define SCREEN_SIZE_Y 1024
#define NET_MASK 0xff
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(context) This is supposed to be the subnetmask of your LAN. It is required for correctly grouping the connections by ip.


SDL_Window *window;
SDL_Renderer *renderer;
Expand All @@ -27,7 +31,101 @@ pthread_t canvas_thread;
} \
} while (0)

#define WHITE (SDL_Color){0xff, 0xff, 0xff, 0xff}

#define FONT_TEXTURE_SIZE 512
#define GLYPH_SIZE 256

struct FontTexture {
SDL_Rect glyphs[GLYPH_SIZE];
SDL_Texture * texture;
} fontTexture;

enum FontStatus {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern does not really fit into the codebase.
(I copied this from an earlier test-version of mine)

Success,
InvalidArg,
InitFailed,
FailedOpen,
FontTooBig,
};

enum FontStatus init_font(SDL_Renderer * renderer) {
SDL_Surface * text = NULL;
SDL_Surface * surface = NULL;

TTF_Font * font = NULL;
enum FontStatus status = Success;

if(renderer == NULL) {
status = InvalidArg;
goto exit;
}

if(TTF_Init()) {
status = InitFailed;
goto exit;
}

font = TTF_OpenFont("./fonts/SourceCodePro-Regular.ttf", 10);

if(font == NULL) {
status = FailedOpen;
goto exit;
}

surface = SDL_CreateRGBSurface(0, FONT_TEXTURE_SIZE, FONT_TEXTURE_SIZE, 32, 0, 0, 0, 0xff);

/* load all ascii printable characters into the glyph atlas */
size_t x = 0;
size_t y = 0;
for(char c = ' '; c <= '~'; c++) {
int w, h;

const char ctext[] = {c, 0};
text = TTF_RenderUTF8_Blended(font, ctext, WHITE);
assert(TTF_SizeText(font, ctext, &w, &h) == 0);

if (x + w >= FONT_TEXTURE_SIZE) {
x = 0;
y += h+1;
}

if (y + h >= FONT_TEXTURE_SIZE) {
status = FontTooBig;
goto exit;
}

{
SDL_Rect * rect;

rect = fontTexture.glyphs + (size_t)c;
rect->x = x;
rect->y = y;
rect->w = w;
rect->h = h;

SDL_BlitSurface(text, NULL, surface, rect);
}

x += w;

SDL_FreeSurface(text);
}

/* obtain a texture containing all the glyphs we are interested in */
fontTexture.texture = SDL_CreateTextureFromSurface(renderer, surface);

exit:
SDL_FreeSurface(surface);
TTF_CloseFont(font);
return status;
}

void canvas_stop(void) {
if (fontTexture.texture) {
SDL_DestroyTexture(fontTexture.texture);
fontTexture.texture = NULL;
}
if (screen_texture) {
SDL_DestroyTexture(screen_texture);
screen_texture = NULL;
Expand All @@ -43,10 +141,53 @@ void canvas_stop(void) {
SDL_Quit();
}


void canvas_connection_draw() {
size_t i = 0;

/* start drawing at the upper right corner */
int x = 0;
int y = 0;

/* compute the pixels set for an ip */
unsigned int ip_buckets[NET_MASK + 1];
memset(ip_buckets, 0, (NET_MASK + 1) * sizeof(*ip_buckets));
for(i = 0; i < num_conns; i++){
size_t lsb = (conns + i)->addr.sin_addr.s_addr & NET_MASK;
ip_buckets[lsb] += (conns + i)->tracker.pixels_set;
}

for(i = 0; i < NET_MASK + 1; i++){
if (ip_buckets[i] == 0) {
continue;
}
char text_buffer[0x100];
memset(text_buffer, 0, sizeof(text_buffer));

snprintf(text_buffer, sizeof(text_buffer), "ip: 192.168.2.%03ld %d",
i, ip_buckets[i]);

size_t j = 0;
int max_height = 0;
for(j = 0; j < sizeof(text_buffer) && text_buffer[j]; j++) {
SDL_Rect src = fontTexture.glyphs[(size_t)text_buffer[j]];
SDL_Rect dst = {.x=x, .y=y, .w=src.w, .h=src.h};
SDL_RenderCopy(renderer, fontTexture.texture, &src, &dst);
x += dst.w;
if (dst.h > max_height) {
max_height = dst.h;
}
}
x = 0;
y += max_height + 1;
}
}

void canvas_draw(void) {
// ? SDL_RenderClear(renderer);
SDL_UpdateTexture(screen_texture, NULL, pixels, TEX_SIZE_X*4);
SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
canvas_connection_draw();
SDL_RenderPresent(renderer);
}

Expand All @@ -66,6 +207,8 @@ void canvas_start(void) {
SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING,
TEX_SIZE_X, TEX_SIZE_Y);
CLEANUP_AND_EXIT_IF(screen_texture == NULL, "SDL_CreateTexture");

CLEANUP_AND_EXIT_IF(init_font(renderer), "init_font");
}

int canvas_set_px(const struct pixel *px) {
Expand Down
2 changes: 1 addition & 1 deletion connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ void connection_tracker_init(struct connection_tracker *t, in_addr_t addr, unsig
void connection_tracker_print(const struct connection_tracker *t) {
printf("Tracker {\n");
printf(" ip: %d.%d.%d.%d,\n", t->addr & 0xff, (t->addr >> 8) & 0xff, (t->addr >> 16) & 0xff, (t->addr >> 24) & 0xff);
printf(" pixels_set: %d,\n", t->pixels_set);
printf(" start_time: %lld,\n", t->start_time);
printf(" end_time: %lld,\n", t->end_time);
printf("}\n");

}

void rect_iter_init(struct rect_iter *r) {
Expand Down
7 changes: 7 additions & 0 deletions connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
#include <sys/socket.h>
#include "buffer.h"

#define MAX_CONNS 1024
#include <netinet/in.h>

void set_nonblocking(int fd);

struct connection_tracker {
in_addr_t addr;
unsigned int pixels_set;
unsigned long long start_time;
unsigned long long end_time;
};
Expand Down Expand Up @@ -38,6 +42,9 @@ struct connection {
struct buffer sendbuf;
};

extern struct connection conns[MAX_CONNS];
extern size_t num_conns;

void connection_print(const struct connection *c);
void connection_init(struct connection *c, int connfd, struct sockaddr_in connaddr);
void connection_close(struct connection *c);
Expand Down
Binary file added fonts/SourceCodePro-Regular.ttf
Binary file not shown.
2 changes: 1 addition & 1 deletion net.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
// if one connection in the middle is removed, conns[num_conns - 1] is moved in its spot.
// this is like rust's Vec::swap_remove.
// when iterating over the connections, we need to make sure that the one that got swapped is not skipped.
#define MAX_CONNS 1024
struct connection conns[MAX_CONNS];
size_t num_conns = 0;
pthread_t net_thread;
Expand Down Expand Up @@ -95,6 +94,7 @@ static void *net_thread_main(void *arg) {

int status = connection_recv(c, &px);
if (status == COMMAND_MULTIRECV_NEXT || status == COMMAND_PRINT) {
c->tracker.pixels_set++;
canvas_set_px(&px);
} else if (status == COMMAND_GET) {
int inside_canvas = canvas_get_px(&px);
Expand Down