Initial integration of Cmocka (not finished)
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
add_subdirectory(client)
|
||||
add_subdirectory(session)
|
||||
@@ -0,0 +1,18 @@
|
||||
add_library(client STATIC)
|
||||
|
||||
target_link_libraries(client
|
||||
PRIVATE
|
||||
db
|
||||
main
|
||||
murmur3
|
||||
OpenSSL::Crypto
|
||||
)
|
||||
|
||||
target_sources(client
|
||||
PRIVATE
|
||||
client.c
|
||||
PUBLIC
|
||||
FILE_SET HEADERS
|
||||
FILES
|
||||
client.h
|
||||
)
|
||||
@@ -0,0 +1,104 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/* Copyright (c) 2026 Oleksandr Zhylin */
|
||||
|
||||
#include "client.h"
|
||||
#include "file_p.h"
|
||||
#include <main.h>
|
||||
#include "session.h"
|
||||
#include "utils.h"
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DEF_LIMIT 15
|
||||
#define DEF_PAGE_NUM 1
|
||||
|
||||
void process_client_command(char *line, session *sess, server_data_t *s_d) {
|
||||
char arg_1[32];
|
||||
char arg_2[32];
|
||||
int32_t res;
|
||||
i_file_list_t fl_args;
|
||||
fl_args.name = NULL;
|
||||
int32_t ret = 0;
|
||||
|
||||
sscanf(line, "%s %s", arg_1, arg_2);
|
||||
|
||||
if (!strcmp(arg_1, "file")) {
|
||||
/* LIST */
|
||||
if (!strcmp(arg_2, "list")) {
|
||||
ret = sscanf(line, "%*s %*s %u %u", &(fl_args.limit), &(fl_args.page));
|
||||
switch (ret) {
|
||||
case EOF:
|
||||
case 0:
|
||||
fl_args.limit = DEF_LIMIT;
|
||||
case 1:
|
||||
fl_args.page = DEF_PAGE_NUM;
|
||||
}
|
||||
file_list(sess, s_d, &fl_args);
|
||||
return;
|
||||
}
|
||||
|
||||
/* UPLOAD */
|
||||
if (!strcmp(arg_2, "upload")) {
|
||||
res = file_receive_prepare(sess, line, s_d);
|
||||
if (!res)
|
||||
sess->state = OP_UPLOAD;
|
||||
return;
|
||||
}
|
||||
|
||||
/* DOWNLOAD */
|
||||
if (!strcmp(arg_2, "download")) {
|
||||
res = file_send_prepare(sess, line, s_d);
|
||||
if (!res)
|
||||
sess->state = OP_DOWNLOAD;
|
||||
return;
|
||||
}
|
||||
|
||||
/* SEARCH */
|
||||
if (!strcmp(arg_2, "search")) {
|
||||
char *s_type = arg_1; /* since we don't need the contents of arg_1 and
|
||||
arg_2 variables */
|
||||
char *s_val = arg_2;
|
||||
ret = sscanf(line, "%*s %*s %s %s %u %u", s_type, s_val, &(fl_args.limit),
|
||||
&(fl_args.page));
|
||||
|
||||
switch (ret) {
|
||||
case 2:
|
||||
fl_args.limit = DEF_LIMIT;
|
||||
case 3:
|
||||
fl_args.page = DEF_PAGE_NUM;
|
||||
}
|
||||
|
||||
/* by name */
|
||||
if (!strcmp(s_type, "name")) {
|
||||
fl_args.name = s_val;
|
||||
}
|
||||
|
||||
file_list(sess, s_d, &fl_args);
|
||||
}
|
||||
}
|
||||
|
||||
if (!strncmp(line, "exit", sizeof "exit")) {
|
||||
sess->state = ERR;
|
||||
sess->reason = EXIT;
|
||||
session_send_string(sess, "OK. Bye!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void download_confirm(char *line, session *sess, server_data_t *s_d) {
|
||||
if (!strncmp(line, "continue", sizeof "continue" - 1)) {
|
||||
int pac_siz = 0;
|
||||
sscanf(line, "continue %d\n", &pac_siz);
|
||||
sess->state = OP_DOWNLOAD;
|
||||
sess->file->package_rest = pac_siz;
|
||||
return;
|
||||
}
|
||||
if (!strncmp(line, "cancel", sizeof "cancel" - 1)) {
|
||||
print_log(stdout, pl_info, "Downloading of %s is canceled by the client\n",
|
||||
sess->file->name);
|
||||
clear_file_from_sess(sess);
|
||||
sess->state = OP_WAIT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/* Copyright (c) 2026 Oleksandr Zhylin */
|
||||
|
||||
#ifndef CLIENT_H
|
||||
#define CLIENT_H
|
||||
|
||||
#include <main.h>
|
||||
void process_client_command(char *line, session *sess, server_data_t *s_d);
|
||||
void download_confirm(char *line, session *sess, server_data_t *s_d);
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
add_library(session STATIC)
|
||||
|
||||
target_link_libraries(session
|
||||
PRIVATE
|
||||
client
|
||||
db
|
||||
murmur3
|
||||
OpenSSL::Crypto
|
||||
)
|
||||
|
||||
target_sources(session
|
||||
PRIVATE
|
||||
session.c
|
||||
PUBLIC
|
||||
FILE_SET HEADERS
|
||||
FILES
|
||||
session.h
|
||||
)
|
||||
@@ -0,0 +1,235 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/* Copyright (c) 2026 Oleksandr Zhylin */
|
||||
|
||||
#include "session.h"
|
||||
#include "../../client.h"
|
||||
#include "../../file_p.h"
|
||||
#include "../../main.h"
|
||||
#include "../../user.h"
|
||||
#include "../../utils.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <db.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
session *make_new_session(int fd, struct sockaddr_in *from, char *wm);
|
||||
|
||||
int32_t accept_client(int ls, session *connections[], char *wm) {
|
||||
int sd;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
sd = accept(ls, (struct sockaddr *)&addr, &len);
|
||||
if (sd == -1) {
|
||||
perror("accept");
|
||||
return -1;
|
||||
}
|
||||
session *sess = make_new_session(sd, &addr, wm);
|
||||
print_log(stdout, pl_info, "New connection: %s:%u\n",
|
||||
inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
|
||||
connections[sd] = sess;
|
||||
return 0;
|
||||
}
|
||||
|
||||
session *make_new_session(int fd, struct sockaddr_in *from, char *wm) {
|
||||
struct session *sess = malloc(sizeof(*sess));
|
||||
sess->from_ip = ntohl(from->sin_addr.s_addr);
|
||||
sess->from_port = ntohs(from->sin_port);
|
||||
sess->buf_used = 0;
|
||||
sess->state = OP_LOGIN_USR;
|
||||
sess->reason = NO_REASON;
|
||||
sess->uname = NULL;
|
||||
sess->sd = fd;
|
||||
sess->fd = -1;
|
||||
sess->file = NULL;
|
||||
sess->fl_start = NULL;
|
||||
sess->fl_current = NULL;
|
||||
session_send_string(sess, wm);
|
||||
session_send_string(sess, "login> ");
|
||||
return sess;
|
||||
}
|
||||
|
||||
void session_send_string(struct session *sess, const char *fmt, ...) {
|
||||
char buf[INBUFSIZE];
|
||||
size_t b_len = 0;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
b_len = vsprintf(buf, fmt, args);
|
||||
write(sess->sd, buf, b_len);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
int session_do_read(session *sess, char **read_str) {
|
||||
int rc, bufp = sess->buf_used;
|
||||
rc = read(sess->sd, sess->buf + bufp, INBUFSIZE - bufp);
|
||||
sess->buf[bufp + rc] = 0;
|
||||
if (rc <= 0) {
|
||||
sess->state = ERR;
|
||||
return 0;
|
||||
}
|
||||
sess->buf_used += rc;
|
||||
char *line;
|
||||
query_extract_from_buf(sess, &line);
|
||||
if (line == NULL) {
|
||||
*read_str = line;
|
||||
return 0;
|
||||
} else {
|
||||
*read_str = line;
|
||||
}
|
||||
if (sess->buf_used >= INBUFSIZE) {
|
||||
/* we can't read further, no room in the buffer, no whole line yet */
|
||||
session_send_string(sess, "Line too long! Good bye...\n");
|
||||
sess->state = ERR;
|
||||
return 0;
|
||||
}
|
||||
if (sess->state == FIN)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int query_extract_from_buf(session *sess, char **output_line) {
|
||||
char *line;
|
||||
int pos = -1;
|
||||
|
||||
if (sess->buf_used > 0) {
|
||||
char *cptr = strchr(sess->buf, '\n');
|
||||
if (cptr != NULL)
|
||||
pos = cptr - sess->buf;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos == -1) {
|
||||
int b_used = sess->buf_used;
|
||||
sess->buf_used = 0;
|
||||
line = malloc(b_used + 1);
|
||||
strncpy(line, sess->buf, b_used);
|
||||
|
||||
line[b_used] = 0;
|
||||
|
||||
*output_line = line;
|
||||
return b_used;
|
||||
} else {
|
||||
line = malloc(pos + 2);
|
||||
strncpy(line, sess->buf, pos + 1);
|
||||
line[++pos] = 0;
|
||||
sess->buf_used -= (pos);
|
||||
if (!pos)
|
||||
pos++;
|
||||
memmove(sess->buf, sess->buf + pos, sess->buf_used);
|
||||
sess->buf[sess->buf_used] = 0;
|
||||
if (line[pos - 2] == '\r') {
|
||||
line[pos - 2] = line[pos - 1];
|
||||
pos--;
|
||||
line[pos - 1] = 0;
|
||||
}
|
||||
*output_line = line;
|
||||
}
|
||||
return pos + 1;
|
||||
}
|
||||
|
||||
int query_extract_from_buf_2(char *buf, ssize_t *buf_used, char **output_line) {
|
||||
char *line;
|
||||
int pos = -1;
|
||||
int _buf_used = *buf_used;
|
||||
|
||||
if (_buf_used > 0) {
|
||||
char *cptr = strchr(buf, '\n');
|
||||
if (cptr != NULL)
|
||||
pos = cptr - buf;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos == -1) {
|
||||
int b_used = _buf_used;
|
||||
*buf_used = 0;
|
||||
line = malloc(b_used + 1);
|
||||
strncpy(line, buf, b_used);
|
||||
|
||||
line[b_used] = 0;
|
||||
|
||||
*output_line = line;
|
||||
return b_used;
|
||||
} else {
|
||||
line = malloc(pos + 2);
|
||||
strncpy(line, buf, pos + 1);
|
||||
line[++pos] = 0;
|
||||
_buf_used -= (pos);
|
||||
if (!pos)
|
||||
pos++;
|
||||
memmove(buf, buf + pos, _buf_used);
|
||||
buf[_buf_used] = 0;
|
||||
if (line[pos - 2] == '\r') {
|
||||
line[pos - 2] = line[pos - 1];
|
||||
pos--;
|
||||
line[pos - 1] = 0;
|
||||
}
|
||||
*output_line = line;
|
||||
*buf_used = _buf_used;
|
||||
}
|
||||
return pos + 1;
|
||||
}
|
||||
|
||||
void perform_session_action(session *sess, char *line, server_data_t *s_d) {
|
||||
int state = sess->state;
|
||||
int res;
|
||||
/* while (sess->buf_used) { */
|
||||
switch (state) {
|
||||
case OP_LOGIN_USR:
|
||||
process_user_name(line, sess);
|
||||
break;
|
||||
case OP_LOGIN_PSS:
|
||||
login(sess, line);
|
||||
break;
|
||||
case OP_WAIT:
|
||||
process_client_command(line, sess, s_d);
|
||||
break;
|
||||
case OP_DOWNLOAD:
|
||||
file_download(sess);
|
||||
break;
|
||||
case OP_UPLOAD:
|
||||
file_upload(sess);
|
||||
break;
|
||||
case OP_UPLOAD_DESCRIPTION:
|
||||
res = file_upload_description(sess, line, s_d);
|
||||
if (res) {
|
||||
if (db_save_file(sess)) {
|
||||
session_send_string(sess, "File \"%s\" is saved!\04\n",
|
||||
sess->file->name);
|
||||
clear_file_from_sess(sess);
|
||||
sess->state = OP_WAIT;
|
||||
} else {
|
||||
// TODO: error case
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OP_DOWNLOAD_WAIT_CONFIRM_PACKAGE:
|
||||
download_confirm(line, sess, s_d);
|
||||
break;
|
||||
}
|
||||
/* } */
|
||||
}
|
||||
|
||||
void close_session(session *connections[], int sd) {
|
||||
if (connections[sd] != NULL) {
|
||||
if (connections[sd]->file != NULL)
|
||||
clear_file_from_sess(connections[sd]);
|
||||
close(sd);
|
||||
connections[sd]->sd = -1;
|
||||
free(connections[sd]->uname);
|
||||
if (connections[sd]->fl_start != NULL) {
|
||||
fl_t *fl_start = connections[sd]->fl_start;
|
||||
clear_list(fl_start);
|
||||
}
|
||||
free(connections[sd]);
|
||||
connections[sd] = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/* Copyright (c) 2026 Oleksandr Zhylin */
|
||||
|
||||
#ifndef SESSION_H
|
||||
#define SESSION_H
|
||||
#include "../../main.h"
|
||||
#include <stdio.h>
|
||||
int accept_client(int ls, session *connections[], char *wm);
|
||||
void session_send_string(struct session *sess, const char *str, ...);
|
||||
int query_extract_from_buf(session *sess, char **output_line);
|
||||
int session_do_read(session *sess, char **read_str);
|
||||
void perform_session_action(session *sess, char *line, server_data_t *s_d);
|
||||
void close_session(session *connections[], int sd);
|
||||
int query_extract_from_buf_2(char *buf, ssize_t *buf_used, char **output_line);
|
||||
/* session *make_new_session(int fd, struct sockaddr_in *from, char *wm); */
|
||||
/* int query_extract_from_sess(session *sess, char **output_line); */
|
||||
#endif
|
||||
Reference in New Issue
Block a user