From 7c321d614e8d91b23434b13bfcf89274797815ec Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Sat, 22 Apr 2017 22:24:06 +0200 Subject: Initial Commit. --- src/meta_net/CMakeLists.txt | 9 ++ src/meta_net/meta_net.c | 158 ++++++++++++++++++++++++ src/meta_net/meta_net.h | 82 +++++++++++++ src/meta_net/meta_net_handle_reply.c | 74 +++++++++++ src/meta_net/meta_net_select.c | 53 ++++++++ src/meta_net/meta_net_try_request.c | 232 +++++++++++++++++++++++++++++++++++ src/meta_net/meta_net_types.h | 26 ++++ 7 files changed, 634 insertions(+) create mode 100644 src/meta_net/CMakeLists.txt create mode 100644 src/meta_net/meta_net.c create mode 100644 src/meta_net/meta_net.h create mode 100644 src/meta_net/meta_net_handle_reply.c create mode 100644 src/meta_net/meta_net_select.c create mode 100644 src/meta_net/meta_net_try_request.c create mode 100644 src/meta_net/meta_net_types.h (limited to 'src/meta_net') diff --git a/src/meta_net/CMakeLists.txt b/src/meta_net/CMakeLists.txt new file mode 100644 index 0000000..ca047c3 --- /dev/null +++ b/src/meta_net/CMakeLists.txt @@ -0,0 +1,9 @@ +set( + SRC_FILES ${SRC_FILES} + ${CMAKE_CURRENT_SOURCE_DIR}/meta_net.c + ${CMAKE_CURRENT_SOURCE_DIR}/meta_net_handle_reply.c + ${CMAKE_CURRENT_SOURCE_DIR}/meta_net_select.c + ${CMAKE_CURRENT_SOURCE_DIR}/meta_net_try_request.c +) + +set(SRC_FILES ${SRC_FILES} PARENT_SCOPE) diff --git a/src/meta_net/meta_net.c b/src/meta_net/meta_net.c new file mode 100644 index 0000000..fdd0fec --- /dev/null +++ b/src/meta_net/meta_net.c @@ -0,0 +1,158 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../error/error.h" + +#include "../parameters/parameters.h" + +#include "meta_net.h" + +static int open_socket +( + struct JH_meta_net s [const restrict static 1], + const char socket_name [const restrict static 1] +) +{ + struct sockaddr_un addr; + int flags; + const int old_errno = errno; + + errno = 0; + + s->fd = socket(AF_UNIX, SOCK_STREAM, 0); + + if (s->fd == -1) + { + JH_FATAL + ( + stderr, + "Unable to create socket: %s.", + strerror(errno) + ); + + errno = old_errno; + + return -1; + } + + errno = old_errno; + + memset((void *) &addr, 0, sizeof(addr)); + + addr.sun_family = AF_UNIX; + + strncpy + ( + (void *) addr.sun_path, + (const void *) socket_name, + (sizeof(addr.sun_path) - 1) + ); + + errno = 0; + + if (connect(s->fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) + { + JH_FATAL + ( + stderr, + "Unable to connect to address: %s.", + strerror(errno) + ); + + errno = old_errno; + + close(s->fd); + + return -1; + } + + errno = 0; + + flags = fcntl(s->fd, F_GETFD, 0); + + if (flags < 0) + { + JH_FATAL + ( + stderr, + "Unable to get fd flag information for JabberHive socket: %s.", + strerror(errno) + ); + + errno = old_errno; + + close(s->fd); + + return -1; + } + + errno = 0; + + if (fcntl(s->fd, F_SETFL, (flags | O_NONBLOCK)) == -1) + { + JH_FATAL + ( + stderr, + "Unable to get fd flag information for JabberHive socket: %s.", + strerror(errno) + ); + + errno = old_errno; + + close(s->fd); + + return -1; + } + + errno = old_errno; + + return 0; +} + +int JH_meta_net_connect +( + struct JH_meta_net socket [const restrict static 1], + const struct JH_parameters params [const restrict static 1] +) +{ + return + open_socket + ( + socket, + JH_parameters_get_socket_name(params) + ); +} + +void JH_meta_net_initialize +( + struct JH_meta_net socket [const restrict static 1] +) +{ + socket->in.data = (char *) NULL; + socket->in.capacity = 0; + socket->in.length = 0; + socket->in.index = 0; + + socket->out.data = (char *) NULL; + socket->out.capacity = 0; + socket->out.length = 0; + socket->out.index = 0; + + socket->fd = -1; + socket->has_request_in_progress = 0; +} + +void JH_meta_net_finalize +( + struct JH_meta_net socket [const restrict static 1] +) +{ + /* TODO */ +} diff --git a/src/meta_net/meta_net.h b/src/meta_net/meta_net.h new file mode 100644 index 0000000..ce5c61e --- /dev/null +++ b/src/meta_net/meta_net.h @@ -0,0 +1,82 @@ +#ifndef _JH_META_NET_META_NET_H_ +#define _JH_META_NET_META_NET_H_ + +#include "../parameters/parameters_types.h" + +#include "../irc/irc_types.h" + +#include "meta_net_types.h" + +void JH_meta_net_initialize +( + struct JH_meta_net socket [const restrict static 1] +); + +int JH_meta_net_connect +( + struct JH_meta_net socket [const restrict static 1], + const struct JH_parameters params [const restrict static 1] +); + +void JH_meta_net_finalize +( + struct JH_meta_net socket [const restrict static 1] +); + +int JH_meta_net_try_request +( + struct JH_meta_net socket [const restrict static 1], + const char string [const restrict static 1], + const size_t string_size +); + +int JH_meta_net_handle_user_message +( + struct JH_meta_net socket [const restrict static 1], + const char string [const restrict static 1], + const size_t string_size +); + +int JH_meta_net_handle_user_action +( + struct JH_meta_net socket [const restrict static 1], + const char string [const restrict static 1], + const size_t string_size +); + +int JH_meta_net_read +( + struct JH_meta_net socket [const restrict static 1] +); + +/* TODO */ +int JH_meta_net_write +( + struct JH_meta_net socket [const restrict static 1] +); + +void JH_meta_net_handle_reply +( + struct JH_meta_net socket [const restrict static 1], + struct JH_irc irc [const restrict static 1], + const struct JH_parameters params [const restrict static 1] +); + +int JH_meta_net_pre_select +( + struct JH_meta_net socket [const restrict static 1], + const struct JH_parameters params [const restrict static 1], + fd_set in [const restrict static 1], + fd_set out [const restrict static 1], + int max_fd [const restrict static 1] +); + +int JH_meta_net_post_select +( + struct JH_meta_net socket [const restrict static 1], + const struct JH_parameters params [const restrict static 1], + fd_set in [const restrict static 1], + fd_set out [const restrict static 1] +); + +#endif diff --git a/src/meta_net/meta_net_handle_reply.c b/src/meta_net/meta_net_handle_reply.c new file mode 100644 index 0000000..b823078 --- /dev/null +++ b/src/meta_net/meta_net_handle_reply.c @@ -0,0 +1,74 @@ +#include "../error/error.h" + +#include "../irc/irc.h" +#include "../parameters/parameters.h" + +#include "meta_net.h" + +void JH_meta_net_handle_reply +( + struct JH_meta_net socket [const restrict static 1], + struct JH_irc irc [const restrict static 1], + const struct JH_parameters params [const restrict static 1] +) +{ + if (socket->in.index == 0) + { + /* No reply to handle. */ + return; + } + + socket->in.data[socket->in.index] = '\0'; + + if (JH_IS_PREFIX("!CPV ", socket->in.data)) + { + } + else if (JH_IS_PREFIX("!CPS ", socket->in.data)) + { + } + else if (JH_IS_PREFIX("!GR ", socket->in.data)) + { + /* TODO: /me vs message should be handled prior to this. */ + JH_irc_send_message(irc, (socket->in.data + 4)); + + JH_DEBUG + ( + stderr, + /* TODO: Parameter dependent behavior. */ + JH_DEBUG_DISPLAY_IRC_MSG_EXCHANGES, + "<%s> %s", + JH_parameters_get_irc_nick(params), + (socket->in.data + 4) + ); + } + else if (JH_IS_PREFIX("!AI ", socket->in.data)) + { + /* TODO: Parameter dependent behavior. */ + JH_DEBUG + ( + stderr, + 1, + "Received: %s.", + socket->in.data + ); + } + else if (JH_IS_PREFIX("!P ", socket->in.data)) + { + socket->has_request_in_progress = 0; + } + else if (JH_IS_PREFIX("!N ", socket->in.data)) + { + JH_S_WARNING(stderr, "Received Negative reply."); + + socket->has_request_in_progress = 0; + } + else + { + JH_WARNING + ( + stderr, + "Unsupported reply received: %s.", + socket->in.data + ); + } +} diff --git a/src/meta_net/meta_net_select.c b/src/meta_net/meta_net_select.c new file mode 100644 index 0000000..069a671 --- /dev/null +++ b/src/meta_net/meta_net_select.c @@ -0,0 +1,53 @@ +#include +#include + +#include "meta_net.h" + +int JH_meta_net_pre_select +( + struct JH_meta_net socket [const restrict static 1], + const struct JH_parameters params [const restrict static 1], + fd_set in [const restrict static 1], + fd_set out [const restrict static 1], + int max_fd [const restrict static 1] +) +{ + FD_SET(socket->fd, in); + FD_SET(socket->fd, out); + + if ((*max_fd) < socket->fd) + { + *max_fd = socket->fd; + } + + return 0; +} + +int JH_meta_net_post_select +( + struct JH_meta_net socket [const restrict static 1], + const struct JH_parameters params [const restrict static 1], + fd_set in [const restrict static 1], + fd_set out [const restrict static 1] +) +{ + if (FD_ISSET(socket->fd, in)) + { + if (JH_meta_net_read(socket) < 0) + { + /* TODO: Try to reconnect. */ + return -1; + } + } + + if (FD_ISSET(socket->fd, out)) + { + if (JH_meta_net_write(socket) < 0) + { + /* TODO: Try to reconnect. */ + return -1; + } + } + + return 0; +} diff --git a/src/meta_net/meta_net_try_request.c b/src/meta_net/meta_net_try_request.c new file mode 100644 index 0000000..121ef8d --- /dev/null +++ b/src/meta_net/meta_net_try_request.c @@ -0,0 +1,232 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../error/error.h" + +#include "../parameters/parameters.h" + +#include "meta_net.h" + +/******************************************************************************/ +/** MEMORY ALLOCATION *********************************************************/ +/******************************************************************************/ +static int ensure_string_capacity +( + char * string [const restrict static 1], + size_t string_capacity [const restrict static 1], + const size_t string_required_capacity +) +{ + char * new_string; + + if (string_required_capacity <= *string_capacity) + { + return 0; + } + + new_string = + (char *) realloc + ( + (void *) *string, + ((size_t) string_required_capacity) * sizeof(char) + ); + + if (new_string == (char *) NULL) + { + JH_S_ERROR + ( + stderr, + "Unable to reallocate memory to match string's required size." + ); + + return -1; + } + + *string_capacity = string_required_capacity; + *string = new_string; + + return 1; +} + +/******************************************************************************/ +/** EXPORTED ******************************************************************/ +/******************************************************************************/ +int JH_meta_net_handle_user_message +( + struct JH_meta_net socket [const restrict static 1], + const char string [const restrict static 1], + const size_t string_size +) +{ + if (socket->out.length != 0) + { + return 1; + } + + if + ( + ensure_string_capacity + ( + &(socket->out.data), + &(socket->out.capacity), + string_size + ) + < 0 + ) + { + return -1; + } + + memcpy + ( + (void *) socket->out.data, + (const void *) string, + (string_size * sizeof(char)) + ); + + socket->out.length = string_size; + socket->out.index = 0; + + socket->has_request_in_progress = 1; + + return 0; +} + +int JH_meta_net_handle_user_action +( + struct JH_meta_net socket [const restrict static 1], + const char string [const restrict static 1], + const size_t string_size +) +{ + if (socket->out.length != 0) + { + return 1; + } + + if + ( + ensure_string_capacity + ( + &(socket->out.data), + &(socket->out.capacity), + (string_size + (JH_META_NET_ACTION_STRING_LENGTH + 1)) + ) + < 0 + ) + { + return -1; + } + + memcpy + ( + (void *) socket->out.data, + (const void *) JH_META_NET_ACTION_STRING, + (JH_META_NET_ACTION_STRING_LENGTH * sizeof(char)) + ); + + socket->out.data[JH_META_NET_ACTION_STRING_LENGTH] = ' '; + + memcpy + ( + (void *) (socket->out.data + (JH_META_NET_ACTION_STRING_LENGTH + 1)), + (const void *) string, + (string_size * sizeof(char)) + ); + + socket->out.length = string_size; + socket->out.index = 0; + + socket->has_request_in_progress = 1; + + return 0; +} + +int JH_meta_net_read +( + struct JH_meta_net socket [const restrict static 1] +) +{ + const int old_errno = errno; + ssize_t in_bytes_count; + + if ((SIZE_MAX - JH_META_NET_READ_SIZE) < socket->in.length) + { + JH_S_ERROR + ( + stderr, + "Unable to read from JabberHive socket: max buffer size reached." + ); + + return -1; + } + + if + ( + ensure_string_capacity + ( + &(socket->in.data), + &(socket->in.capacity), + (socket->in.length + JH_META_NET_READ_SIZE) + ) + < 0 + ) + { + return -1; + } + + errno = 0; + + in_bytes_count = + read + ( + socket->fd, + (&(socket->in.data) + socket->in.length), + (size_t) JH_META_NET_READ_SIZE + ); + + if (in_bytes_count < 0) + { + if (errno == EAGAIN) + { + errno = old_errno; + + return 0; + } + + JH_ERROR + ( + stderr, + "Unable to read from JabberHive socket: %s.", + strerror(errno) + ); + + errno = old_errno; + + return -1; + } + + errno = old_errno; + + /* Safe. */ + socket->in.length += (size_t) in_bytes_count; + + while (socket->in.index < socket->in.length) + { + if (socket->in.data[socket->in.index] == '\n') + { + break; + } + + socket->in.index += 1; + } + + return 0; +} diff --git a/src/meta_net/meta_net_types.h b/src/meta_net/meta_net_types.h new file mode 100644 index 0000000..251f85b --- /dev/null +++ b/src/meta_net/meta_net_types.h @@ -0,0 +1,26 @@ +#ifndef _JH_META_NET_META_NET_TYPES_H_ +#define _JH_META_NET_META_NET_TYPES_H_ + +#include + +#define JH_META_NET_READ_SIZE 64 +#define JH_META_NET_ACTION_STRING "/me" +#define JH_META_NET_ACTION_STRING_LENGTH 3 + +struct JH_meta_net_buffer +{ + char * data; + size_t capacity; + size_t length; + size_t index; +}; + +struct JH_meta_net +{ + int fd; + int has_request_in_progress; + struct JH_meta_net_buffer in; + struct JH_meta_net_buffer out; +}; + +#endif -- cgit v1.2.3-70-g09d2