Files
KoboShare/KoboShare_server.c
2026-06-12 20:44:16 +02:00

192 lines
5.2 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <SDL2/SDL.h>
#define PORT 8080
#define TCP_PACKET_SIZE 1024 // 1KB chunks for sending
typedef struct SDLFramework {
SDL_Window* window;
SDL_Renderer* renderer;
SDL_Texture* texture;
} SDLFramework;
int TCP_connect(int *fd) {
int server_fd, client_fd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
// Create socket
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
perror("Can't create socket");
return -1;
}
// Allow port reuse
int opt = 1;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
// Setup server address
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
// Bind socket
if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Can't bind");
close(server_fd);
return -1;
}
// Listen for connections
if (listen(server_fd, 1) < 0) {
perror("Can't listen");
close(server_fd);
return -1;
}
printf("Server listening on port %d...\n", PORT);
client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len);
if (client_fd < 0) {
perror("Can't accept");
close(server_fd);
return -1;
}
printf("Connection accepted from %s:%d\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
fd[0] = server_fd;
fd[1] = client_fd;
return 0;
}
void TCP_disconnect(int *fd) {
close(fd[0]); // server_fd
close(fd[1]); // client_fd
}
void TCP_screen_info(int *fd, int *width, int *height, int *bpp, size_t *buffer_size) {
recv(fd[1], width, sizeof(int), 0);
recv(fd[1], height, sizeof(int), 0);
recv(fd[1], bpp, sizeof(int), 0);
*buffer_size = (*width) * (*height) * (*bpp / 8);
printf("width = %d\n", *width);
printf("height = %d\n", *height);
printf("bpp = %d\n", *bpp);
printf("buffer_size = %zu\n", *buffer_size);
}
unsigned char *TCP_receive_data(int client_fd, size_t buffer_size) {
// Allocate the buffer with the size that the client communicated
unsigned char *buffer = malloc(buffer_size);
if (!buffer) {
perror("malloc failed");
return NULL;
}
int total_received = 0;
while (total_received < buffer_size) {
// Calculate how many byte i still have to receive (could be TCP_PACKET_SIZE or less)
int to_receive = 0;
if (buffer_size - total_received > TCP_PACKET_SIZE) {
to_receive= TCP_PACKET_SIZE;
} else {
to_receive = (buffer_size - total_received);
}
// Receive the package and update the total_sent value
int received = recv(client_fd, buffer + total_received, to_receive, 0);
total_received += received;
}
return buffer;
}
void initialize_SDL(SDLFramework *framework, int width, int height) {
SDL_Init(SDL_INIT_VIDEO);
framework->window = SDL_CreateWindow("Viewer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE);
framework->renderer = SDL_CreateRenderer(framework->window, -1, SDL_RENDERER_ACCELERATED);
framework->texture = SDL_CreateTexture(framework->renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, width, height);
return;
}
int main() {
int fd[2]; // array containing server_fd as first element and client_fd as second
unsigned char *buffer;
int width;
int height;
int bpp;
size_t buffer_size;
SDLFramework framework;
SDL_Event event;
int windowWidth, windowHeight;
// Connecting to the client and receiving the screen information
TCP_connect(fd);
TCP_screen_info(fd, &width, &height, &bpp, &buffer_size);
initialize_SDL(&framework, width, height);
int i=0;
while(1){
// Receiving from the client the buffer
buffer = TCP_receive_data(fd[1], buffer_size);
printf("Buffer received[%d]\n", i);
// Handle the event (if quit then TODO, if resize just aknowledge (the rendering will handle this))
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
}
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) {
}
}
// Display the image
SDL_UpdateTexture(framework.texture, NULL, buffer, width * 4);
SDL_RenderClear(framework.renderer);
SDL_GetWindowSize(framework.window, &windowWidth, &windowHeight);
SDL_Rect destRect = {0, 0, windowWidth, windowHeight};
SDL_RenderCopy(framework.renderer, framework.texture, NULL, &destRect);
SDL_RenderPresent(framework.renderer);
i++;
}
// Cleaning
SDL_DestroyTexture(framework.texture);
SDL_DestroyRenderer(framework.renderer);
SDL_DestroyWindow(framework.window);
SDL_Quit();
TCP_disconnect(fd);
return 0;
}