fix memory leak
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "myclib/hashmap/myhashmap.h"
|
#include "myclib/hashmap/myhashmap.h"
|
||||||
#include "utils/config.h"
|
#include "utils/config.h"
|
||||||
@@ -45,6 +46,11 @@ typedef enum cws_server_ret_t {
|
|||||||
CWS_SERVER_EPOLL_CREATE_ERROR,
|
CWS_SERVER_EPOLL_CREATE_ERROR,
|
||||||
} cws_server_ret;
|
} cws_server_ret;
|
||||||
|
|
||||||
|
typedef struct cws_client_info_t {
|
||||||
|
time_t last_activity;
|
||||||
|
int client_fd;
|
||||||
|
} cws_client_info;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Runs the server
|
* @brief Runs the server
|
||||||
*
|
*
|
||||||
@@ -97,9 +103,9 @@ int cws_server_accept_client(int server_fd, struct sockaddr_storage *their_sa, s
|
|||||||
*
|
*
|
||||||
* @param[in] epfd Epoll file descriptor
|
* @param[in] epfd Epoll file descriptor
|
||||||
* @param[in] client_fd Client file descriptor
|
* @param[in] client_fd Client file descriptor
|
||||||
* @param[in] hashmap Clients hash map
|
* @param[in] clients Clients hash map
|
||||||
*/
|
*/
|
||||||
void cws_server_close_client(int epfd, int client_fd, mcl_hashmap *hashmap);
|
void cws_server_close_client(int epfd, int client_fd, mcl_hashmap *clients);
|
||||||
|
|
||||||
int cws_server_handle_new_client(int server_fd, int epfd, mcl_hashmap *clients);
|
int cws_server_handle_new_client(int server_fd, int epfd, mcl_hashmap *clients);
|
||||||
void *cws_server_handle_client_data(void *arg);
|
void *cws_server_handle_client_data(void *arg);
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
typedef struct cws_task_t {
|
typedef struct cws_task_t {
|
||||||
int client_fd;
|
int client_fd;
|
||||||
|
int epfd;
|
||||||
|
mcl_hashmap *clients;
|
||||||
cws_config *config;
|
cws_config *config;
|
||||||
} cws_task;
|
} cws_task;
|
||||||
|
|
||||||
|
|||||||
@@ -152,13 +152,16 @@ cws_server_ret cws_server_loop(int server_fd, cws_config *config) {
|
|||||||
|
|
||||||
for (int i = 0; i < nfds; ++i) {
|
for (int i = 0; i < nfds; ++i) {
|
||||||
if (revents[i].data.fd == server_fd) {
|
if (revents[i].data.fd == server_fd) {
|
||||||
|
/* Handle new client */
|
||||||
int client_fd = cws_server_handle_new_client(server_fd, epfd, clients);
|
int client_fd = cws_server_handle_new_client(server_fd, epfd, clients);
|
||||||
if (client_fd < 0) {
|
if (client_fd < 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cws_epoll_add(epfd, client_fd, EPOLLIN | EPOLLET);
|
cws_epoll_add(epfd, client_fd, EPOLLIN | EPOLLET);
|
||||||
cws_fd_set_nonblocking(client_fd);
|
cws_fd_set_nonblocking(client_fd);
|
||||||
|
mcl_hm_set(clients, &client_fd, "test");
|
||||||
} else {
|
} else {
|
||||||
|
/* Handle client data */
|
||||||
int client_fd = revents[i].data.fd;
|
int client_fd = revents[i].data.fd;
|
||||||
|
|
||||||
cws_task *task = malloc(sizeof(cws_task));
|
cws_task *task = malloc(sizeof(cws_task));
|
||||||
@@ -170,6 +173,8 @@ cws_server_ret cws_server_loop(int server_fd, cws_config *config) {
|
|||||||
|
|
||||||
task->client_fd = client_fd;
|
task->client_fd = client_fd;
|
||||||
task->config = config;
|
task->config = config;
|
||||||
|
task->epfd = epfd;
|
||||||
|
task->clients = clients;
|
||||||
|
|
||||||
cws_thread_task *ttask = malloc(sizeof(cws_thread_task));
|
cws_thread_task *ttask = malloc(sizeof(cws_thread_task));
|
||||||
if (!ttask) {
|
if (!ttask) {
|
||||||
@@ -182,6 +187,11 @@ cws_server_ret cws_server_loop(int server_fd, cws_config *config) {
|
|||||||
ttask->function = (void *)cws_server_handle_client_data;
|
ttask->function = (void *)cws_server_handle_client_data;
|
||||||
|
|
||||||
ret = cws_threadpool_submit(pool, ttask);
|
ret = cws_threadpool_submit(pool, ttask);
|
||||||
|
if (ret != CWS_SERVER_OK) {
|
||||||
|
cws_server_close_client(epfd, client_fd, clients);
|
||||||
|
free(task);
|
||||||
|
}
|
||||||
|
|
||||||
free(ttask);
|
free(ttask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,40 +259,41 @@ void *cws_server_handle_client_data(void *arg) {
|
|||||||
cws_task *task = (cws_task *)arg;
|
cws_task *task = (cws_task *)arg;
|
||||||
|
|
||||||
int client_fd = task->client_fd;
|
int client_fd = task->client_fd;
|
||||||
|
int epfd = task->epfd;
|
||||||
|
mcl_hashmap *clients = task->clients;
|
||||||
cws_config *config = task->config;
|
cws_config *config = task->config;
|
||||||
|
|
||||||
/* Read data from socket */
|
/* Read data from socket */
|
||||||
mcl_string *data = NULL;
|
mcl_string *data = NULL;
|
||||||
size_t total_bytes = cws_read_data(client_fd, &data);
|
size_t total_bytes = cws_read_data(client_fd, &data);
|
||||||
if (total_bytes < 0) {
|
if (total_bytes <= 0) {
|
||||||
|
if (data) {
|
||||||
mcl_string_free(data);
|
mcl_string_free(data);
|
||||||
free(task);
|
|
||||||
|
|
||||||
/* TODO: Here we should close the client_fd, same as total == 0 */
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
cws_server_close_client(epfd, client_fd, clients);
|
||||||
if (total_bytes == 0) {
|
free(task);
|
||||||
mcl_string_free(data);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse HTTP request */
|
/* Parse HTTP request */
|
||||||
// CWS_LOG_DEBUG("Raw request: %s", mcl_string_cstr(data));
|
|
||||||
cws_http *request = cws_http_parse(data, client_fd, config);
|
cws_http *request = cws_http_parse(data, client_fd, config);
|
||||||
mcl_string_free(data);
|
mcl_string_free(data);
|
||||||
|
|
||||||
if (request == NULL) {
|
if (request == NULL) {
|
||||||
|
cws_server_close_client(epfd, client_fd, clients);
|
||||||
|
free(task);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: fix keep-alive */
|
int keepalive = cws_http_send_resource(request);
|
||||||
int _keepalive = cws_http_send_resource(request);
|
|
||||||
cws_http_free(request);
|
cws_http_free(request);
|
||||||
|
if (!keepalive) {
|
||||||
|
CWS_LOG_DEBUG("keep-alive: %d, closing fd: %d", keepalive, client_fd);
|
||||||
|
cws_server_close_client(epfd, client_fd, clients);
|
||||||
|
}
|
||||||
|
|
||||||
/* Free the task */
|
|
||||||
free(task);
|
free(task);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -337,10 +348,12 @@ int cws_server_accept_client(int server_fd, struct sockaddr_storage *their_sa, s
|
|||||||
return client_fd;
|
return client_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cws_server_close_client(int epfd, int client_fd, mcl_hashmap *hashmap) {
|
void cws_server_close_client(int epfd, int client_fd, mcl_hashmap *clients) {
|
||||||
if (fcntl(client_fd, F_GETFD) != -1) {
|
/* TODO: fix race conditions */
|
||||||
/* TODO: race condition here */
|
mcl_bucket *client = mcl_hm_get(clients, &client_fd);
|
||||||
|
if (client) {
|
||||||
cws_epoll_del(epfd, client_fd);
|
cws_epoll_del(epfd, client_fd);
|
||||||
mcl_hm_remove(hashmap, &client_fd);
|
mcl_hm_remove(clients, &client_fd);
|
||||||
|
mcl_hm_free_bucket(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user