diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..317379d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.15) + +project(ctest LANGUAGES C) + +add_compile_options(-pthread) + +set(PROJ_BUILD_DIR ${CMAKE_BINARY_DIR}) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJ_BUILD_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJ_BUILD_DIR}/bin) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJ_BUILD_DIR}/bin) + +set(PROJ_REL_BUILD_DIR ${CMAKE_BINARY_DIR}/release) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${PROJ_REL_BUILD_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${PROJ_REL_BUILD_DIR}/bin) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJ_REL_BUILD_DIR}/bin) + +set(PROJ_DEB_BUILD_DIR ${CMAKE_BINARY_DIR}/debug) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${PROJ_DEB_BUILD_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${PROJ_DEB_BUILD_DIR}/bin) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJ_DEB_BUILD_DIR}/bin) + + +add_subdirectory(src) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..35e52ff --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,6 @@ + +add_executable(ctest + "main.c" + "sockets.h") + +add_subdirectory(sockets) diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..675831c --- /dev/null +++ b/src/main.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include "sockets.h" + + +static void sig_handler(); + +int main(int argc, char *argv[]) +{ + signal(SIGINT, sig_handler); + if (argc == 2) + { + if (strcmp(argv[1], "server") == 0) + { + return start_server(); + } + if (strcmp(argv[1], "client") == 0) + { + clientstart(); + return 0; + } + } + + printf("None or too much arguments passed!\n"); + return 0; +} + +// Handle the signal to exit the app! +static void sig_handler() +{ + stop_server(); + exit(0); +} diff --git a/src/sockets.h b/src/sockets.h new file mode 100644 index 0000000..31cda95 --- /dev/null +++ b/src/sockets.h @@ -0,0 +1,23 @@ +#ifndef SOCKETS_H +#define SOCKETS_H +#include +#include +#include +#include + +#define PORT_NUM 42069 + +struct net_data +{ + char sName[100]; +}; + +void clientstart(); +int start_server(); +int stop_server(); + + +int writeToSock(int fd, void* data, ssize_t size); +int readFromSock(int fd, void* buff, ssize_t size); + +#endif diff --git a/src/sockets/CMakeLists.txt b/src/sockets/CMakeLists.txt new file mode 100644 index 0000000..28190ff --- /dev/null +++ b/src/sockets/CMakeLists.txt @@ -0,0 +1,7 @@ + +target_sources(ctest PRIVATE + "client.c" + "sock_helper.c" + "server.c" + "thread_manager.c" + "thread_manager.h") diff --git a/src/sockets/client.c b/src/sockets/client.c new file mode 100644 index 0000000..70caa6a --- /dev/null +++ b/src/sockets/client.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include +#include +#include +#include "../sockets.h" + + +void clientstart() +{ + int client_sockfd = socket(AF_INET, SOCK_STREAM, 0); + + struct sockaddr_in client_sockaddr; + client_sockaddr.sin_family = AF_INET; + client_sockaddr.sin_port = htons(PORT_NUM); + client_sockaddr.sin_addr.s_addr = INADDR_ANY; + + int connection_status = connect(client_sockfd, (struct sockaddr*) &client_sockaddr, sizeof(client_sockaddr)); + if (connection_status != 0) + { + printf("ERROR: Could not connect!\n"); + return; + } + + ssize_t nextRecSize = 0; + ssize_t recvRead = readFromSock(client_sockfd, &nextRecSize, sizeof(uint32_t)); + if (recvRead == -1) + { + printf("ERROR: Failed to receive data!\nErrno: %i", errno); + return; + } + + nextRecSize = ntohl(nextRecSize); + char serverName[64]; + recvRead = readFromSock(client_sockfd, &serverName, nextRecSize); + if (recvRead == -1) + return; + if (recvRead == 0) + { + printf("No data received!\n"); + } + + printf("Connected with: %s\n", serverName); + + for (;;) + { + char c = getchar(); + if (c == 'q') + return; + } +} diff --git a/src/sockets/server.c b/src/sockets/server.c new file mode 100644 index 0000000..56b3ace --- /dev/null +++ b/src/sockets/server.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include "../sockets.h" +#include "thread_manager.h" + +int server_sockfd; +struct sockaddr_in server_sockaddr; +bool b_listen = true; +char sName[64] = "Test server Linux\0"; +struct net_data server_data; + +void* thread_client_handler(void* arg); + +int start_server() +{ + // Set up data struct that will be send to the client. + //char sName[11] = "Server net"; + //strcpy(server_data.sName, sName); + + server_sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (server_sockfd < 0) + { + printf("ERROR: Could not create server socket!\n"); + return -1; + } + + server_sockaddr.sin_family = AF_INET; + server_sockaddr.sin_port = htons(PORT_NUM); + server_sockaddr.sin_addr.s_addr = INADDR_ANY; + + int bind_result = bind(server_sockfd, (struct sockaddr *) &server_sockaddr, sizeof(server_sockaddr)); + if (bind_result != 0) + { + printf("ERROR: Cannot bind to socket!\n"); + return -1; + } + + while (b_listen) + { + printf("Waiting for a connection...\n"); + int listen_result = listen(server_sockfd, 1); + if (listen_result == -1) + { + printf("ERROR: Could not listen. code: %i", errno); + return -1; + } + int clientfd = accept(server_sockfd, NULL, NULL); + if (clientfd == -1) + { + printf("ERROR: Could not accept client!"); + continue; + } + if (init_thread(&clientfd, thread_client_handler) == -1) + printf("Warning: Could not establish connection with client!"); + } + return 0; +} +int stop_server() +{ + return 0; +} + +// Function used in thread to handle the connected client. +//TODO: Return a type with status, with message on why a value is returned. +void* thread_client_handler(void* arg) +{ + int client_fd = *(int*)arg; + + // Send data size to client. + ssize_t sNameSize = sizeof(sName); + uint32_t sDataSize = htonl(sNameSize); + int sendResult = writeToSock(client_fd, &sDataSize, sizeof(uint32_t)); + if (sendResult == -1)// If we are not be able to send data, return so the thread can exit. + return NULL; + //char buff_recv[10]; + sendResult = writeToSock(client_fd, &sName, sNameSize); + if (sendResult == -1) + return NULL; + + + char buff[50]; + // Wait for command data from client. + for(;;) + { + printf("Listening to client for data!\n"); + int rec_result; + rec_result = recv(client_fd, buff, sizeof(buff), 0); + if (rec_result == -1) + { + printf("Warning: could not recieve data from client!\n"); + continue; + } + + if (rec_result == 0) + { + printf("Client disconnected!\n"); + break; + } + } + + int close_result = close(client_fd); + printf("Close network result: %i\n", close_result); + return NULL; +} + diff --git a/src/sockets/sock_helper.c b/src/sockets/sock_helper.c new file mode 100644 index 0000000..28caf5c --- /dev/null +++ b/src/sockets/sock_helper.c @@ -0,0 +1,34 @@ +#include "../sockets.h" + +int writeToSock(int fd, void* data, ssize_t size) +{ + ssize_t dataSizeSend = 0; + //dataSizeSend += send(fd, data, size, 0); + while (dataSizeSend < size) + { + dataSizeSend += send(fd, (char*)data + dataSizeSend, size - dataSizeSend, 0); + if (dataSizeSend == -1) + { + printf("Warning: Cannot send data!\n"); + return -1; + } + } + return dataSizeSend; +} + +// Do not check for buffer size! +int readFromSock(int fd, void* buff, ssize_t size) +{ + ssize_t dataRecv = 0; + //dataRecv = recv(fd, buff, size, 0); + while (dataRecv < size) + { + dataRecv += recv(fd, (char*)buff + dataRecv, size - dataRecv, 0); + if (dataRecv == -1) + { + printf("Warning: Cannot receive data!\n"); + return -1; + } + } + return dataRecv; +} diff --git a/src/sockets/thread_manager.c b/src/sockets/thread_manager.c new file mode 100644 index 0000000..a4a2d85 --- /dev/null +++ b/src/sockets/thread_manager.c @@ -0,0 +1,16 @@ +#include +#include "thread_manager.h" + +int init_thread(int* clientfd, void *(*func) (void *)) +{ + pthread_t thread; + int thread_create_result = pthread_create(&thread, NULL, func, clientfd); + if (thread_create_result == -1) + { + printf("ERROR: Could not create thread!\n"); + return thread_create_result; + } + printf("Init thread: %lu\n", thread); + return 0; +} + diff --git a/src/sockets/thread_manager.h b/src/sockets/thread_manager.h new file mode 100644 index 0000000..673228b --- /dev/null +++ b/src/sockets/thread_manager.h @@ -0,0 +1,8 @@ +#ifndef THREAD_MANAGER_H +#define THREAD_MANAGER_H +#include +#include "../sockets.h" + +int init_thread(int* clientfd, void *(*func) (void *)); + +#endif