192 lines
5.2 KiB
C
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;
|
|
|
|
} |