diff --git a/03_io_access/lib/io.c b/03_io_access/lib/io.c index 8552713..874e33a 100644 --- a/03_io_access/lib/io.c +++ b/03_io_access/lib/io.c @@ -13,6 +13,7 @@ static struct gpiod_line *button_line = NULL; // Error handling function static int handle_error(const char *msg) { perror(msg); + cleanup_gpio() return -1; } diff --git a/04_intro_to_sockets/Makefile b/04_intro_to_sockets/Makefile index 393b7ba..116698d 100644 --- a/04_intro_to_sockets/Makefile +++ b/04_intro_to_sockets/Makefile @@ -1,10 +1,11 @@ +# Compiler and flags CC = gcc CFLAGS = -Wall -Ilib -#LDFLAGS = -lgpiod # Directories SRCDIR = src LIBDIR = lib +BINDIR = bin OBJDIR = obj # Source files @@ -13,27 +14,26 @@ SRC_SOURCES = $(wildcard $(SRCDIR)/*.c) # Object files LIB_OBJECTS = $(LIB_SOURCES:$(LIBDIR)/%.c=$(OBJDIR)/%.o) -SRC_OBJECTS = $(SRC_SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o) -# Target executable -TARGET = sockets +# Executables +EXECS = $(SRC_SOURCES:$(SRCDIR)/%.c=$(BINDIR)/%) -# Create obj directory if it doesn't exist +# Create necessary directories $(shell mkdir -p $(OBJDIR)) +$(shell mkdir -p $(BINDIR)) # Rules -all: $(TARGET) +all: $(EXECS) -$(TARGET): $(LIB_OBJECTS) $(SRC_OBJECTS) - $(CC) $(LIB_OBJECTS) $(SRC_OBJECTS) -o $@ $(LDFLAGS) +$(BINDIR)/%: $(SRCDIR)/%.c $(LIB_OBJECTS) + $(CC) $(CFLAGS) -o $@ $< $(LIB_OBJECTS) $(OBJDIR)/%.o: $(LIBDIR)/%.c $(CC) $(CFLAGS) -c $< -o $@ -$(OBJDIR)/%.o: $(SRCDIR)/%.c - $(CC) $(CFLAGS) -c $< -o $@ - clean: - rm -f $(OBJDIR)/*.o $(TARGET) + rm -f $(OBJDIR)/*.o + rm -f $(BINDIR)/* .PHONY: all clean + diff --git a/04_intro_to_sockets/README.md b/04_intro_to_sockets/README.md index efc3305..eb91d03 100644 --- a/04_intro_to_sockets/README.md +++ b/04_intro_to_sockets/README.md @@ -7,5 +7,5 @@ a LED, a button and a temperature sensor. ```bash $ make -$ ./io +$ ./sockets ``` diff --git a/04_intro_to_sockets/bin/daytimeTCPCli b/04_intro_to_sockets/bin/daytimeTCPCli new file mode 100755 index 0000000..549cb11 Binary files /dev/null and b/04_intro_to_sockets/bin/daytimeTCPCli differ diff --git a/04_intro_to_sockets/bin/daytimeTCPSrv b/04_intro_to_sockets/bin/daytimeTCPSrv new file mode 100755 index 0000000..6d094af Binary files /dev/null and b/04_intro_to_sockets/bin/daytimeTCPSrv differ diff --git a/04_intro_to_sockets/lib/sockets.c b/04_intro_to_sockets/lib/sockets.c index e69de29..7031a77 100644 --- a/04_intro_to_sockets/lib/sockets.c +++ b/04_intro_to_sockets/lib/sockets.c @@ -0,0 +1,113 @@ +#include // For inet_addr(), htons() +#include // For printf() +#include // For exit() +#include // For memset() +#include // For socket(), connect(), read(), write() +#include +#include // For close() +#include "sockets.h" + +#define BUFFER_SIZE 1024 + +static void error_handling(char *message, int sock) { + perror(message); + close(sock); + exit(1); +} + +int tcp_create_socket() { + // PF_INET: IPv4, SOCK_STREAM: TCP + int sock = socket(PF_INET, SOCK_STREAM, 0); + if (sock == -1) + error_handling("socket() error", sock); + return sock; +} + +void connect_to_server(int sock, char *ip, int port) { + struct sockaddr_in serv_addr; + // Initialize serv_addr to zero + memset(&serv_addr, 0, sizeof(serv_addr)); + // Set the address family to IPv4 + serv_addr.sin_family = AF_INET; + // Convert IP address to binary form + serv_addr.sin_addr.s_addr = inet_addr(ip); + // Convert port number to network byte order + serv_addr.sin_port = htons(port); + + if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) + error_handling("connect() error", sock); +} + +char* communicate(int sock, char *message) { + // Sending the ASCII string + if (write(sock, message, strlen(message)) == -1) + error_handling("write() error", sock); + + // Receiving response + char* response = malloc(BUFFER_SIZE); + if (!response) + error_handling("Failed to allocate memory for response", sock); + + int str_len = read(sock, response, BUFFER_SIZE - 1); + if (str_len == -1){ + free(response); + error_handling("read() error", sock); + } else if (str_len == 0) { + printf("Server closed the connection.\n"); + free(response); + return NULL; + } else { + response[str_len] = '\0'; // Null-terminate the received data + } + return response; +} + +int tcp_listen(int port) { + int sock = tcp_create_socket(); + + struct sockaddr_in serv_addr; + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(port); + + if (bind(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) + error_handling("bind() error", sock); + + if (listen(sock, 5) == -1) + error_handling("listen() error", sock); + + return sock; +} + +int tcp_accept(int serv_sock) { + struct sockaddr_in clnt_addr; + socklen_t clnt_addr_size = sizeof(clnt_addr); + int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size); + if (clnt_sock == -1) + error_handling("accept() error", clnt_sock); + return clnt_sock; +} + +void process_request(int clnt_sock) { + char message[BUFFER_SIZE]; + int str_len = read(clnt_sock, message, BUFFER_SIZE - 1); + if (str_len == -1) + // TODO: clnt_sock might be a bug + error_handling("read() error", clnt_sock); + + message[str_len] = '\0'; // Null-terminate the string + + time_t t = time(NULL); + struct tm *timeinfo; + + if (strcmp(message, "1") == 0) { + timeinfo = localtime(&t); // Local time + } else { + timeinfo = gmtime(&t); // GMT time + } + + strftime(message, BUFFER_SIZE, "%Y-%m-%d %H:%M:%S", timeinfo); + write(clnt_sock, message, strlen(message)); +} + diff --git a/04_intro_to_sockets/lib/sockets.h b/04_intro_to_sockets/lib/sockets.h index ab5885f..cf6322d 100644 --- a/04_intro_to_sockets/lib/sockets.h +++ b/04_intro_to_sockets/lib/sockets.h @@ -1,5 +1,22 @@ #ifndef SOCKETS_LIB_H #define SOCKETS_LIB_H +// Function to create a TCP socket +int tcp_create_socket(); -#endif // SOCKETS_H +// Function to connect to a server +void connect_to_server(int sock, char *ip, int port); + +// Function to communicate with the server +char* communicate(int sock, char *message); + +// Function to create a TCP server socket +int tcp_listen(int port); + +// Function to accept a client connection +int tcp_accept(int serv_sock); + +// Function to process a client request +void process_request(int clnt_sock); + +#endif // SOCKETS_LIB_H diff --git a/04_intro_to_sockets/obj/sockets.o b/04_intro_to_sockets/obj/sockets.o new file mode 100644 index 0000000..a45d678 Binary files /dev/null and b/04_intro_to_sockets/obj/sockets.o differ diff --git a/04_intro_to_sockets/src/daytimeTCPCli.c b/04_intro_to_sockets/src/daytimeTCPCli.c new file mode 100644 index 0000000..93badde --- /dev/null +++ b/04_intro_to_sockets/src/daytimeTCPCli.c @@ -0,0 +1,21 @@ +#include // For printf() +#include // For close() +#include // For exit(), atoi() +#include "sockets.h" + +int main(int argc, char *argv[]) { + if (argc != 4) { + printf("Usage : %s \n", argv[0]); + exit(1); + } + + int sock = tcp_create_socket(); + connect_to_server(sock, argv[1], atoi(argv[2])); + char* received_data = communicate(sock, argv[3]); + if (received_data) { + printf("Received from server: %s\n", received_data); + free(received_data); + } + close(sock); + return 0; +} diff --git a/04_intro_to_sockets/src/daytimeTCPSrv.c b/04_intro_to_sockets/src/daytimeTCPSrv.c new file mode 100644 index 0000000..634f84a --- /dev/null +++ b/04_intro_to_sockets/src/daytimeTCPSrv.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include "sockets.h" + +int main(int argc, char *argv[]) { + if (argc != 2) { + printf("Usage: %s \n", argv[0]); + exit(1); + } + + int port = atoi(argv[1]); + int serv_sock = tcp_listen(port); + int clnt_sock = tcp_accept(serv_sock); + + process_request(clnt_sock); + close(clnt_sock); + close(serv_sock); + return 0; +} diff --git a/04_intro_to_sockets/src/main.c b/04_intro_to_sockets/src/main.c deleted file mode 100644 index 2b8c6ac..0000000 --- a/04_intro_to_sockets/src/main.c +++ /dev/null @@ -1,4 +0,0 @@ - -int main() { - return 0; -}