Last active
August 29, 2015 14:10
-
-
Save GuillaumeGomez/be77af3fa6e8daa4388d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <netinet/ip.h> | |
#include <netdb.h> | |
#include <arpa/inet.h> | |
#include <net/if.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#define PORT 4242 | |
#define READ 1 | |
#define WRITE 2 | |
#define ALLOC 3 | |
// [ID][BEGIN_POINTER][REQUEST] | |
// [CHAR][UNSIGNED LONG][UNSIGNED LONG] | |
typedef struct netmalloc { | |
unsigned long begin; | |
unsigned int size; | |
char *pointer; | |
struct netmalloc *next; | |
} netmalloc; | |
int get_all_data(void *data, int size, int sock) { | |
int rec = 0; | |
int tmp; | |
char *c_data = data; | |
while (rec < size) { | |
if ((tmp = recv(sock, c_data + rec, size - rec, 0)) < 1) | |
return 0; | |
rec += tmp; | |
} | |
return 1; | |
} | |
int send_all_data(void *data, int size, int sock) { | |
int rec = 0; | |
int tmp; | |
char *c_data = data; | |
while (rec < size) { | |
if ((tmp = send(sock, c_data + rec, size - rec, 0)) < 1) | |
return 0; | |
rec += tmp; | |
} | |
return 1; | |
} | |
void add_new_element(netmalloc **head, unsigned long begin_pointer, unsigned int malloc_size) { | |
if (!*head) { | |
*head = malloc(sizeof(netmalloc)); | |
(*head)->pointer = malloc(malloc_size); | |
(*head)->size = malloc_size; | |
(*head)->next = 0; | |
(*head)->begin = begin_pointer; | |
return; | |
} | |
netmalloc *tmp = *head; | |
netmalloc *new = malloc(sizeof(*new)); | |
while (tmp->next) { | |
tmp = tmp->next; | |
} | |
new->pointer = malloc(malloc_size); | |
new->size = malloc_size; | |
new->next = 0; | |
new->begin = begin_pointer; | |
tmp->next = new; | |
} | |
int handle_write(netmalloc *head, unsigned long begin_pointer, unsigned long from_pointer, | |
unsigned int write_size, int sock) { | |
while (head) { | |
if (head->begin == begin_pointer) | |
break; | |
head = head->next; | |
} | |
if (!head) | |
return 1; | |
if (!get_all_data(head->pointer + (from_pointer - begin_pointer), write_size, sock)) | |
return 0; | |
return 1; | |
} | |
int handle_read(netmalloc *head, unsigned long begin_pointer, unsigned long from_pointer, | |
unsigned int read_size, int sock) { | |
while (head) { | |
if (head->begin == begin_pointer) | |
break; | |
head = head->next; | |
} | |
if (!head) | |
return 1; | |
if (!send_all_data(head->pointer + (from_pointer - begin_pointer), read_size, sock)) | |
return 0; | |
return 1; | |
} | |
void handle_client(int client) | |
{ | |
netmalloc *head = 0; | |
for (;;) { | |
char id; | |
unsigned long begin_pointer; | |
unsigned long from_pointer; | |
unsigned int malloc_size; | |
if (!get_all_data(&id, sizeof(id), client)) | |
break; | |
if (id == READ) { | |
if (!get_all_data(&begin_pointer, sizeof(begin_pointer), client)) | |
break; | |
if (!get_all_data(&from_pointer, sizeof(from_pointer), client)) | |
break; | |
if (!get_all_data(&malloc_size, sizeof(malloc_size), client)) | |
break; | |
if (!handle_read(head, begin_pointer, from_pointer, malloc_size, client)) | |
break; | |
} else if (id == WRITE) { | |
if (!get_all_data(&begin_pointer, sizeof(begin_pointer), client)) | |
break; | |
if (!get_all_data(&from_pointer, sizeof(from_pointer), client)) | |
break; | |
if (!get_all_data(&malloc_size, sizeof(malloc_size), client)) | |
break; | |
if (!handle_write(head, begin_pointer, from_pointer, malloc_size, client)) | |
break; | |
} else if (id == ALLOC) { | |
if (!get_all_data(&begin_pointer, sizeof(begin_pointer), client)) | |
break; | |
if (!get_all_data(&malloc_size, sizeof(malloc_size), client)) | |
break; | |
add_new_element(&head, begin_pointer, malloc_size); | |
} | |
} | |
while (head) { | |
netmalloc *tmp = head->next; | |
free(head->pointer); | |
free(head); | |
head = tmp; | |
} | |
} | |
int main(void) | |
{ | |
struct sockaddr_in sin; | |
int sock; | |
socklen_t recsize = sizeof(sin); | |
struct sockaddr_in csin; | |
int csock; | |
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | |
perror("socket"); | |
return EXIT_FAILURE; | |
} | |
sin.sin_addr.s_addr = htonl(INADDR_ANY); | |
sin.sin_family = AF_INET; | |
sin.sin_port = htons(PORT); | |
if (bind(sock, (struct sockaddr*)&sin, recsize)) { | |
perror("bind"); | |
close(sock); | |
return EXIT_FAILURE; | |
} | |
if (listen(sock, 1)) { | |
perror("listen"); | |
close(sock); | |
return EXIT_FAILURE; | |
} | |
printf("Waiting client\n"); | |
if ((csock = accept(sock, (struct sockaddr*)&csin, &recsize)) < 0) { | |
perror("accept"); | |
close(sock); | |
return EXIT_FAILURE; | |
} | |
handle_client(csock); | |
printf("Client connected\n"); | |
close(csock); | |
close(sock); | |
printf("Server is shutting down\n"); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment