summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2017-04-22 22:24:06 +0200
committerNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2017-04-22 22:24:06 +0200
commit7c321d614e8d91b23434b13bfcf89274797815ec (patch)
tree58b8e4fcba63b38a052423401df413606a7e8076 /src
Initial Commit.
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt11
-rw-r--r--src/error/CMakeLists.txt6
-rw-r--r--src/error/error.h143
-rw-r--r--src/irc/CMakeLists.txt11
-rw-r--r--src/irc/irc.c110
-rw-r--r--src/irc/irc.h43
-rw-r--r--src/irc/irc_event_handlers.h69
-rw-r--r--src/irc/irc_handle_connected.c27
-rw-r--r--src/irc/irc_handle_dcc_events.c27
-rw-r--r--src/irc/irc_receive.c50
-rw-r--r--src/irc/irc_select.c38
-rw-r--r--src/irc/irc_send.c38
-rw-r--r--src/irc/irc_types.h14
-rw-r--r--src/main.c206
-rw-r--r--src/meta_net/CMakeLists.txt9
-rw-r--r--src/meta_net/meta_net.c158
-rw-r--r--src/meta_net/meta_net.h82
-rw-r--r--src/meta_net/meta_net_handle_reply.c74
-rw-r--r--src/meta_net/meta_net_select.c53
-rw-r--r--src/meta_net/meta_net_try_request.c232
-rw-r--r--src/meta_net/meta_net_types.h26
-rw-r--r--src/parameters/CMakeLists.txt7
-rw-r--r--src/parameters/parameters.c250
-rw-r--r--src/parameters/parameters.h60
-rw-r--r--src/parameters/parameters_getters.c73
-rw-r--r--src/parameters/parameters_types.h21
-rw-r--r--src/pervasive.h31
27 files changed, 1869 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..5d1adf6
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_subdirectory(error)
+add_subdirectory(parameters)
+add_subdirectory(meta_net)
+add_subdirectory(irc)
+
+set(
+ SRC_FILES ${SRC_FILES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/main.c
+)
+
+set(SRC_FILES ${SRC_FILES} PARENT_SCOPE)
diff --git a/src/error/CMakeLists.txt b/src/error/CMakeLists.txt
new file mode 100644
index 0000000..fa07534
--- /dev/null
+++ b/src/error/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(
+ SRC_FILES ${SRC_FILES}
+)
+
+set(SRC_FILES ${SRC_FILES} PARENT_SCOPE)
+
diff --git a/src/error/error.h b/src/error/error.h
new file mode 100644
index 0000000..145c838
--- /dev/null
+++ b/src/error/error.h
@@ -0,0 +1,143 @@
+#ifndef _JH_ERROR_ERROR_H_
+#define _JH_ERROR_ERROR_H_
+
+#include <stdio.h>
+
+#include "../pervasive.h"
+
+#ifndef JH_DEBUG_PROGRAM_FLOW
+ #define JH_DEBUG_PROGRAM_FLOW (0 || JH_DEBUG_ALL)
+#endif
+
+#ifndef JH_DEBUG_CONFIG
+ #define JH_DEBUG_CONFIG (0 || JH_DEBUG_ALL)
+#endif
+
+#ifndef JH_DEBUG_LEARNING
+ #define JH_DEBUG_LEARNING (0 || JH_DEBUG_ALL)
+#endif
+
+#ifndef JH_DEBUG_NETWORK
+ #define JH_DEBUG_NETWORK 1
+#endif
+
+#ifndef JH_DEBUG_NETWORK
+ #define JH_DEBUG_NETWORK (0 || JH_DEBUG_ALL)
+#endif
+
+#define JH_ENABLE_WARNINGS_OUTPUT 1
+#define JH_ENABLE_RUNTIME_ERRORS_OUTPUT 1
+#define JH_ENABLE_PROGRAMMING_ERRORS_OUTPUT 1
+#define JH_ENABLE_FATAL_ERROR_OUTPUT 1
+
+#ifdef JH_ENABLE_ERROR_LOCATION
+ #define JH_LOCATION " [" __FILE__ "][" JH_TO_STRING(__LINE__) "]"
+#else
+ #define JH_LOCATION ""
+#endif
+
+#define JH_PRINT_STDERR(io, symbol, str, ...)\
+ fprintf(io, "[" symbol "]" JH_LOCATION " " str "\n", __VA_ARGS__);
+
+/*
+ * Given that we use preprocessor contants as flags, we can expect the compilers
+ * to remove the test condition for disabled flags. No need to be shy about
+ * allowing many debug options.
+ */
+
+#define JH_DEBUG(io, flag, str, ...)\
+ JH_ISOLATE\
+ (\
+ if (flag)\
+ {\
+ JH_PRINT_STDERR(io, "D", str, __VA_ARGS__);\
+ }\
+ )
+
+
+#define JH_WARNING(io, str, ...)\
+ JH_ISOLATE\
+ (\
+ if (JH_ENABLE_WARNINGS_OUTPUT)\
+ {\
+ JH_PRINT_STDERR(io, "W", str, __VA_ARGS__);\
+ }\
+ )
+
+#define JH_ERROR(io, str, ...)\
+ JH_ISOLATE\
+ (\
+ if (JH_ENABLE_RUNTIME_ERRORS_OUTPUT)\
+ {\
+ JH_PRINT_STDERR(io, "E", str, __VA_ARGS__);\
+ }\
+ )
+
+#define JH_PROG_ERROR(io, str, ...)\
+ JH_ISOLATE\
+ (\
+ if (JH_ENABLE_PROGRAMMING_ERRORS_OUTPUT)\
+ {\
+ JH_PRINT_STDERR(io, "P", str, __VA_ARGS__);\
+ }\
+ )
+
+#define JH_FATAL(io, str, ...)\
+ JH_ISOLATE\
+ (\
+ if (JH_ENABLE_FATAL_ERROR_OUTPUT)\
+ {\
+ JH_PRINT_STDERR(io, "F", str, __VA_ARGS__);\
+ }\
+ )
+
+/* For outputs without dynamic content (static). ******************************/
+
+#define JH_PRINT_S_STDERR(io, symbol, str)\
+ fprintf(io, "[" symbol "]" JH_LOCATION " " str "\n");
+
+#define JH_S_DEBUG(io, flag, str)\
+ JH_ISOLATE\
+ (\
+ if (flag)\
+ {\
+ JH_PRINT_S_STDERR(io, "D", str);\
+ }\
+ )
+
+#define JH_S_WARNING(io, str)\
+ JH_ISOLATE\
+ (\
+ if (JH_ENABLE_WARNINGS_OUTPUT)\
+ {\
+ JH_PRINT_S_STDERR(io, "W", str);\
+ }\
+ )
+
+#define JH_S_ERROR(io, str)\
+ JH_ISOLATE\
+ (\
+ if (JH_ENABLE_RUNTIME_ERRORS_OUTPUT)\
+ {\
+ JH_PRINT_S_STDERR(io, "E", str);\
+ }\
+ )
+
+#define JH_S_PROG_ERROR(io, str)\
+ JH_ISOLATE\
+ (\
+ if (JH_ENABLE_PROGRAMMING_ERRORS_OUTPUT)\
+ {\
+ JH_PRINT_S_STDERR(io, "P", str);\
+ }\
+ )
+
+#define JH_S_FATAL(io, str)\
+ JH_ISOLATE\
+ (\
+ if (JH_ENABLE_FATAL_ERROR_OUTPUT)\
+ {\
+ JH_PRINT_S_STDERR(io, "F", str);\
+ }\
+ )
+#endif
diff --git a/src/irc/CMakeLists.txt b/src/irc/CMakeLists.txt
new file mode 100644
index 0000000..b037d15
--- /dev/null
+++ b/src/irc/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(
+ SRC_FILES ${SRC_FILES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/irc.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/irc_handle_connected.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/irc_handle_dcc_events.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/irc_receive.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/irc_select.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/irc_send.c
+)
+
+set(SRC_FILES ${SRC_FILES} PARENT_SCOPE)
diff --git a/src/irc/irc.c b/src/irc/irc.c
new file mode 100644
index 0000000..3e0bca7
--- /dev/null
+++ b/src/irc/irc.c
@@ -0,0 +1,110 @@
+#include <libircclient/libircclient.h>
+
+#include <string.h>
+
+#include "../error/error.h"
+
+#include "../parameters/parameters.h"
+
+#include "irc.h"
+#include "irc_event_handlers.h"
+
+int JH_irc_initialize
+(
+ struct JH_irc irc [const restrict static 1],
+ const struct JH_parameters params [const restrict static 1],
+ struct JH_meta_net jh_net [const restrict static 1]
+)
+{
+ memset((void *) &(irc->callbacks), 0, sizeof(irc_callbacks_t));
+
+ irc->callbacks.event_connect = JH_irc_handle_connected_event;
+ irc->callbacks.event_join = JH_irc_do_nothing;
+ irc->callbacks.event_nick = JH_irc_do_nothing;
+ irc->callbacks.event_quit = JH_irc_do_nothing;
+ irc->callbacks.event_part = JH_irc_do_nothing;
+ irc->callbacks.event_mode = JH_irc_do_nothing;
+ irc->callbacks.event_topic = JH_irc_do_nothing;
+ irc->callbacks.event_kick = JH_irc_do_nothing;
+ irc->callbacks.event_channel = JH_irc_handle_channel_message_event;
+ irc->callbacks.event_privmsg = JH_irc_do_nothing;
+ irc->callbacks.event_notice = JH_irc_do_nothing;
+ irc->callbacks.event_invite = JH_irc_do_nothing;
+ irc->callbacks.event_umode = JH_irc_do_nothing;
+
+ irc->callbacks.event_ctcp_rep = JH_irc_do_nothing;
+ irc->callbacks.event_ctcp_action = JH_irc_handle_ctcp_action_event;
+ irc->callbacks.event_unknown = JH_irc_do_nothing;
+ irc->callbacks.event_numeric = JH_irc_handle_numeric_event;
+
+ irc->callbacks.event_dcc_chat_req = JH_irc_handle_dcc_chat_req_event;
+ irc->callbacks.event_dcc_send_req = JH_irc_handle_dcc_send_req_event;
+
+ irc->session = irc_create_session(&(irc->callbacks));
+
+ irc->params = params;
+ irc->jh_net = jh_net;
+
+ if (!(irc->session))
+ {
+ JH_S_FATAL(stderr, "Unable to create IRC session.");
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int JH_irc_connect (struct JH_irc irc [const restrict static 1])
+{
+ if (JH_parameters_get_irc_is_ipv6(irc->params))
+ {
+ return
+ irc_connect6
+ (
+ irc->session,
+ JH_parameters_get_irc_server(irc->params),
+ JH_parameters_get_irc_port(irc->params),
+ JH_parameters_get_irc_password(irc->params),
+ JH_parameters_get_irc_nick(irc->params),
+ JH_parameters_get_irc_username(irc->params),
+ JH_parameters_get_irc_realname(irc->params)
+ );
+ }
+ else
+ {
+ return
+ irc_connect
+ (
+ irc->session,
+ JH_parameters_get_irc_server(irc->params),
+ JH_parameters_get_irc_port(irc->params),
+ JH_parameters_get_irc_password(irc->params),
+ JH_parameters_get_irc_nick(irc->params),
+ JH_parameters_get_irc_username(irc->params),
+ JH_parameters_get_irc_realname(irc->params)
+ );
+ }
+}
+
+void JH_irc_do_nothing
+(
+ irc_session_t * session,
+ const char * event,
+ const char * origin,
+ const char ** params,
+ unsigned int count
+)
+{
+}
+
+void JH_irc_handle_numeric_event
+(
+ irc_session_t * session,
+ unsigned int event,
+ const char * origin,
+ const char ** params,
+ unsigned int count
+)
+{
+}
diff --git a/src/irc/irc.h b/src/irc/irc.h
new file mode 100644
index 0000000..9bdfcef
--- /dev/null
+++ b/src/irc/irc.h
@@ -0,0 +1,43 @@
+#ifndef _JH_IRC_IRC_H_
+#define _JH_IRC_IRC_H_
+
+#include "../parameters/parameters_types.h"
+
+#include "../meta_net/meta_net.h"
+
+#include "irc_types.h"
+
+int JH_irc_initialize
+(
+ struct JH_irc irc [const restrict static 1],
+ const struct JH_parameters params [const restrict static 1],
+ struct JH_meta_net meta_net [const restrict static 1]
+);
+
+int JH_irc_connect (struct JH_irc irc [const restrict static 1]);
+
+int JH_irc_send_message
+(
+ struct JH_irc irc [const restrict static 1],
+ const char msg [const restrict static 1]
+);
+
+/* TODO */
+void JH_irc_finalize (struct JH_irc irc [const restrict static 1]);
+
+int JH_irc_pre_select
+(
+ struct JH_irc irc [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_irc_post_select
+(
+ struct JH_irc irc [const restrict static 1],
+ fd_set in [const restrict static 1],
+ fd_set out [const restrict static 1]
+);
+
+#endif
diff --git a/src/irc/irc_event_handlers.h b/src/irc/irc_event_handlers.h
new file mode 100644
index 0000000..447fbb6
--- /dev/null
+++ b/src/irc/irc_event_handlers.h
@@ -0,0 +1,69 @@
+#ifndef _JH_IRC_IRC_EVENT_HANDLERS_H_
+#define _JH_IRC_IRC_EVENT_HANDLERS_H_
+
+#include <libircclient/libircclient.h>
+
+void JH_irc_do_nothing
+(
+ irc_session_t * session,
+ const char * event,
+ const char * origin,
+ const char ** params,
+ unsigned int count
+);
+
+void JH_irc_handle_connected_event
+(
+ irc_session_t * session,
+ const char * event,
+ const char * origin,
+ const char ** params,
+ unsigned int count
+);
+
+void JH_irc_handle_channel_message_event
+(
+ irc_session_t * session,
+ const char * event,
+ const char * origin,
+ const char ** params,
+ unsigned int count
+);
+
+void JH_irc_handle_ctcp_action_event
+(
+ irc_session_t * session,
+ const char * event,
+ const char * origin,
+ const char ** params,
+ unsigned int count
+);
+
+void JH_irc_handle_numeric_event
+(
+ irc_session_t * session,
+ unsigned int event,
+ const char * origin,
+ const char ** params,
+ unsigned int count
+);
+
+void JH_irc_handle_dcc_chat_req_event
+(
+ irc_session_t * session,
+ const char * nick,
+ const char * addr,
+ irc_dcc_t dccid
+);
+
+void JH_irc_handle_dcc_send_req_event
+(
+ irc_session_t * session,
+ const char * nick,
+ const char * addr,
+ const char * filename,
+ unsigned long size,
+ irc_dcc_t dccid
+);
+
+#endif
diff --git a/src/irc/irc_handle_connected.c b/src/irc/irc_handle_connected.c
new file mode 100644
index 0000000..3d24af9
--- /dev/null
+++ b/src/irc/irc_handle_connected.c
@@ -0,0 +1,27 @@
+#include <libircclient/libircclient.h>
+
+#include "../parameters/parameters.h"
+
+#include "irc.h"
+#include "irc_event_handlers.h"
+
+void JH_irc_handle_connected_event
+(
+ irc_session_t * session,
+ const char * event,
+ const char * origin,
+ const char ** params,
+ unsigned int count
+)
+{
+ struct JH_irc * irc;
+
+ irc = (struct JH_irc *) irc_get_ctx(session);
+
+ irc_cmd_join
+ (
+ session,
+ JH_parameters_get_irc_channel(irc->params),
+ 0
+ );
+}
diff --git a/src/irc/irc_handle_dcc_events.c b/src/irc/irc_handle_dcc_events.c
new file mode 100644
index 0000000..2fe6904
--- /dev/null
+++ b/src/irc/irc_handle_dcc_events.c
@@ -0,0 +1,27 @@
+#include <libircclient/libircclient.h>
+
+#include "irc_event_handlers.h"
+
+void JH_irc_handle_dcc_chat_req_event
+(
+ irc_session_t * session,
+ const char * nick,
+ const char * addr,
+ irc_dcc_t dccid
+)
+{
+ irc_dcc_decline(session, dccid);
+}
+
+void JH_irc_handle_dcc_send_req_event
+(
+ irc_session_t * session,
+ const char * nick,
+ const char * addr,
+ const char * filename,
+ unsigned long size,
+ irc_dcc_t dccid
+)
+{
+ irc_dcc_decline(session, dccid);
+}
diff --git a/src/irc/irc_receive.c b/src/irc/irc_receive.c
new file mode 100644
index 0000000..0edb324
--- /dev/null
+++ b/src/irc/irc_receive.c
@@ -0,0 +1,50 @@
+#include <string.h>
+
+#include <libircclient/libircclient.h>
+
+#include "../meta_net/meta_net.h"
+
+#include "irc.h"
+#include "irc_event_handlers.h"
+
+void JH_irc_handle_channel_message_event
+(
+ irc_session_t * session,
+ const char * event,
+ const char * origin,
+ const char ** params,
+ unsigned int count
+)
+{
+ struct JH_irc * irc;
+
+ irc = (struct JH_irc *) irc_get_ctx(session);
+
+ JH_meta_net_handle_user_message
+ (
+ irc->jh_net,
+ params[1],
+ strlen(params[1])
+ );
+}
+
+void JH_irc_handle_ctcp_action_event
+(
+ irc_session_t * session,
+ const char * event,
+ const char * origin,
+ const char ** params,
+ unsigned int count
+)
+{
+ struct JH_irc * irc;
+
+ irc = (struct JH_irc *) irc_get_ctx(session);
+
+ JH_meta_net_handle_user_action
+ (
+ irc->jh_net,
+ params[0],
+ strlen(params[0])
+ );
+}
diff --git a/src/irc/irc_select.c b/src/irc/irc_select.c
new file mode 100644
index 0000000..fe15662
--- /dev/null
+++ b/src/irc/irc_select.c
@@ -0,0 +1,38 @@
+#include <libircclient/libircclient.h>
+
+#include "irc.h"
+
+int JH_irc_pre_select
+(
+ struct JH_irc irc [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]
+)
+{
+ while (!irc_is_connected(irc->session))
+ {
+ /* TODO: reconnect or fail. */
+ JH_irc_connect(irc);
+ /* TODO: wait a bit... */
+ }
+
+ irc_add_select_descriptors(irc->session, in, out, max_fd);
+
+ return 0;
+}
+
+int JH_irc_post_select
+(
+ struct JH_irc irc [const restrict static 1],
+ fd_set in [const restrict static 1],
+ fd_set out [const restrict static 1]
+)
+{
+ if (!irc_process_select_descriptors(irc->session, in, out))
+ {
+ /* TODO: reconnect or fail. */
+ }
+
+ return 0;
+}
diff --git a/src/irc/irc_send.c b/src/irc/irc_send.c
new file mode 100644
index 0000000..7e474be
--- /dev/null
+++ b/src/irc/irc_send.c
@@ -0,0 +1,38 @@
+#include <libircclient/libircclient.h>
+
+#include "../pervasive.h"
+
+#include "../parameters/parameters.h"
+
+#include "irc.h"
+
+int JH_irc_send_message
+(
+ struct JH_irc irc [const restrict static 1],
+ const char msg [const restrict static 1]
+)
+{
+ if (JH_IS_PREFIX("/me ", msg))
+ {
+ /* TODO: what to do in case of failure? */
+ (void) irc_cmd_me
+ (
+ irc->session,
+ JH_parameters_get_irc_channel(irc->params),
+ (msg + 4)
+ );
+ }
+ else
+ {
+ /* TODO: what to do in case of failure? */
+ (void) irc_cmd_msg
+ (
+ irc->session,
+ JH_parameters_get_irc_channel(irc->params),
+ msg
+ );
+ }
+
+ return 0;
+}
+
diff --git a/src/irc/irc_types.h b/src/irc/irc_types.h
new file mode 100644
index 0000000..f846076
--- /dev/null
+++ b/src/irc/irc_types.h
@@ -0,0 +1,14 @@
+#ifndef _JH_IRC_IRC_TYPES_H_
+#define _JH_IRC_IRC_TYPES_H_
+
+#include <libircclient/libircclient.h>
+
+struct JH_irc
+{
+ irc_callbacks_t callbacks;
+ irc_session_t * session;
+ const struct JH_parameters * params;
+ struct JH_meta_net * jh_net;
+};
+
+#endif
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..509255c
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,206 @@
+/* According to POSIX.1-2001, POSIX.1-2008 */
+#include <sys/select.h>
+
+#include <stdio.h>
+
+#include "error/error.h"
+
+#include "parameters/parameters.h"
+
+#include "irc/irc.h"
+
+#include "meta_net/meta_net.h"
+
+#include "pervasive.h"
+
+static void print_help (const char runnable [const restrict static 1])
+{
+ printf
+ (
+ "JabberHive - IRC Gateway\n"
+ "Software Version %d\n"
+ "Protocol Version %d\n"
+ "\nUsages:\n"
+ " GATEWAY:\t%s SOCKET_NAME IRC_SERVER IRC_NICK IRC_CHANNEL IRC_PORT"
+ " [OPTIONS]\n"
+ " SHOW HELP:\tAnything else.\n"
+ "\nParameters:\n"
+ " SOCKET_NAME:\tValid UNIX socket.\n"
+ " IRC_SERVER:\tAddress of the IRC server. Prefixing with '#' will"
+ " enable SSL.\n"
+ " IRC_NICK:\tIRC nick to be used.\n"
+ " IRC_CHANNEL:\tIRC channel to connect to.\n"
+ " IRC_PORT:\tPort to use for the IRC connection.\n"
+ "\nOptions:\n"
+ " -6, --ipv6:\tEnables IPv6.\n"
+ " -u USERNAME, --username USERNAME:\tSets the IRC username.\n"
+ " -r REALNAME, --realname REALNAME:\tSets the IRC realname.\n"
+ " -p PASSWORD, --password PASSWORD:\tSets the IRC password.\n",
+ JH_PROGRAM_VERSION,
+ JH_PROTOCOL_VERSION,
+ runnable
+ );
+}
+
+static int initialize
+(
+ struct JH_irc irc [const restrict static 1],
+ struct JH_meta_net socket [const restrict static 1],
+ struct JH_parameters params [const restrict static 1],
+ const int argc,
+ const char * argv [const static argc]
+)
+{
+ if (JH_parameters_initialize(params, argc, argv) < 0)
+ {
+ print_help(argv[0]);
+
+ return -1;
+ }
+
+ JH_meta_net_initialize(socket);
+
+ if (JH_irc_initialize(irc, params, socket) < 0)
+ {
+ JH_meta_net_finalize(socket);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+static int connect_all
+(
+ struct JH_irc irc [const restrict static 1],
+ struct JH_meta_net socket [const restrict static 1],
+ struct JH_parameters params [const restrict static 1]
+)
+{
+ if (JH_meta_net_connect(socket, params) < 0)
+ {
+ return -1;
+ }
+
+ if (JH_irc_connect(irc) < 0)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int event_handling_loop
+(
+ struct JH_irc irc [const restrict static 1],
+ struct JH_meta_net socket [const restrict static 1],
+ struct JH_parameters params [const restrict static 1]
+)
+{
+ struct timeval tv;
+ fd_set in_set, out_set;
+ int fd_max, error;
+
+ for (;;)
+ {
+
+ tv.tv_usec = 250000;
+ tv.tv_sec = 0;
+
+ FD_ZERO(&in_set);
+ FD_ZERO(&out_set);
+
+ fd_max = 0;
+
+ if (JH_irc_pre_select(irc, &in_set, &out_set, &fd_max) < 0)
+ {
+ JH_meta_net_finalize(socket);
+
+ return -1;
+ }
+
+ if
+ (
+ JH_meta_net_pre_select
+ (
+ socket,
+ params,
+ &in_set,
+ &out_set,
+ &fd_max
+ ) < 0
+ )
+ {
+ JH_irc_finalize(irc);
+
+ return -1;
+ }
+
+ error =
+ select
+ (
+ (fd_max + 1),
+ &in_set,
+ &out_set,
+ (fd_set *) NULL,
+ &tv
+ );
+
+ if (error < 0)
+ {
+ JH_ERROR
+ (
+ stderr,
+ "Unable to select the sockets: %s.",
+ strerror(error)
+ );
+ }
+
+ if (JH_irc_post_select(irc, &in_set, &out_set) < 0)
+ {
+ JH_meta_net_finalize(socket);
+
+ return -1;
+ }
+
+ if
+ (
+ JH_meta_net_post_select
+ (
+ socket,
+ params,
+ &in_set,
+ &out_set
+ ) < 0
+ )
+ {
+ JH_irc_finalize(irc);
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int main (const int argc, const char * argv [const static argc])
+{
+ struct JH_parameters params;
+ struct JH_meta_net socket;
+ struct JH_irc irc;
+
+ if (initialize(&irc, &socket, &params, argc, argv) < 0)
+ {
+ return -1;
+ }
+
+ if (connect_all(&irc, &socket, &params) < 0)
+ {
+ JH_irc_finalize(&irc);
+ JH_meta_net_finalize(&socket);
+
+ return -1;
+ }
+
+ return event_handling_loop(&irc, &socket, &params);
+}
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 <sys/socket.h>
+#include <sys/un.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#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 <stdio.h>
+#include <sys/select.h>
+
+#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 <sys/socket.h>
+#include <sys/un.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#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 <stdio.h>
+
+#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
diff --git a/src/parameters/CMakeLists.txt b/src/parameters/CMakeLists.txt
new file mode 100644
index 0000000..2aa7ece
--- /dev/null
+++ b/src/parameters/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(
+ SRC_FILES ${SRC_FILES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/parameters.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/parameters_getters.c
+)
+set(SRC_FILES ${SRC_FILES} PARENT_SCOPE)
+
diff --git a/src/parameters/parameters.c b/src/parameters/parameters.c
new file mode 100644
index 0000000..63556f0
--- /dev/null
+++ b/src/parameters/parameters.c
@@ -0,0 +1,250 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "../error/error.h"
+
+#include "parameters.h"
+
+static int parse_port
+(
+ struct JH_parameters param [const restrict static 1],
+ const char argv [const restrict]
+)
+{
+ long long int input;
+ const int old_errno = errno;
+
+ errno = 0;
+
+ input = strtoll(argv, (char **) NULL, 10);
+
+ if
+ (
+ (errno != 0)
+ || (input > (long long int) USHRT_MAX)
+ || (input < 1)
+ )
+ {
+ JH_FATAL
+ (
+ stderr,
+ "Invalid or value for parameter 'port', accepted "
+ "range is "
+ "[1, %hu] (integer).",
+ USHRT_MAX
+ );
+
+ errno = old_errno;
+
+ return -1;
+ }
+
+ param->port = (unsigned short) input;
+
+ errno = old_errno;
+
+ return 0;
+}
+
+static void set_default_to_all_fields
+(
+ struct JH_parameters param [const restrict static 1]
+)
+{
+ param->socket_name = (const char *) NULL;
+ param->server = (const char *) NULL;
+ param->password = (const char *) NULL;
+ param->nick = (const char *) NULL;
+ param->username = (const char *) NULL;
+ param->realname = (const char *) NULL;
+ param->channel = (const char *) NULL;
+ param->port = 0;
+ param->use_ipv6 = 0;
+}
+
+static int is_valid
+(
+ struct JH_parameters param [const restrict static 1]
+)
+{
+ int valid;
+
+ valid = 1;
+
+ if (param->socket_name == (const char *) NULL)
+ {
+ JH_S_FATAL(stderr, "Missing parameter: Zero of One socket name.");
+
+ valid = 0;
+ }
+
+ if (param->server == (const char *) NULL)
+ {
+ JH_S_FATAL(stderr, "Missing parameter: IRC server address.");
+
+ valid = 0;
+ }
+
+ if (param->nick == (const char *) NULL)
+ {
+ JH_S_FATAL(stderr, "Missing parameter: IRC nick.");
+
+ valid = 0;
+ }
+
+ if (param->channel == (const char *) NULL)
+ {
+ JH_S_FATAL(stderr, "Missing parameter: IRC channel.");
+
+ valid = 0;
+ }
+
+ if (param->port == 0)
+ {
+ JH_S_FATAL(stderr, "Missing parameter: IRC port.");
+
+ valid = 0;
+ }
+
+ return valid;
+}
+
+static void set_parameters
+(
+ struct JH_parameters param [const restrict static 1],
+ int const argc,
+ const char * argv [const static argc]
+)
+{
+ if (argc < 2)
+ {
+ return;
+ }
+
+ param->socket_name = argv[1];
+
+ if (argc < 3)
+ {
+ return;
+ }
+
+ param->server = argv[2];
+
+ if (argc < 4)
+ {
+ return;
+ }
+
+ param->nick = argv[3];
+
+ if (argc < 5)
+ {
+ return;
+ }
+
+ param->channel = argv[4];
+
+ if (argc < 6)
+ {
+ return;
+ }
+
+ parse_port(param, argv[5]);
+}
+
+static int set_options
+(
+ struct JH_parameters param [const restrict static 1],
+ int const argc,
+ const char * argv [const static argc]
+)
+{
+ int i;
+
+ for (i = (JH_PARAMETERS_COUNT + 1); i < argc; ++i)
+ {
+
+ if
+ (
+ JH_STRING_EQUALS("-6", argv[i])
+ || JH_STRING_EQUALS("--ipv6", argv[i])
+ )
+ {
+ param->use_ipv6 = 1;
+ }
+ else if
+ (
+ JH_STRING_EQUALS("-u", argv[i])
+ || JH_STRING_EQUALS("--username", argv[i])
+ )
+ {
+ if (i == (argc - 1))
+ {
+ JH_FATAL(stderr, "Missing value for option \"%s\".", argv[i]);
+
+ return -1;
+ }
+
+ param->username = argv[++i];
+ }
+ else if
+ (
+ JH_STRING_EQUALS("-r", argv[i])
+ || JH_STRING_EQUALS("--realname", argv[i])
+ )
+ {
+ if (i == (argc - 1))
+ {
+ JH_FATAL(stderr, "Missing value for option \"%s\".", argv[i]);
+
+ return -1;
+ }
+
+ param->realname = argv[++i];
+ }
+ else if
+ (
+ JH_STRING_EQUALS("-p", argv[i])
+ || JH_STRING_EQUALS("--password", argv[i])
+ )
+ {
+ if (i == (argc - 1))
+ {
+ JH_FATAL(stderr, "Missing value for option \"%s\".", argv[i]);
+
+ return -1;
+ }
+
+ param->password = argv[++i];
+ }
+ else
+ {
+ JH_FATAL(stderr, "Unrecognized option \"%s\".", argv[i]);
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int JH_parameters_initialize
+(
+ struct JH_parameters param [const restrict static 1],
+ int const argc,
+ const char * argv [const static argc]
+)
+{
+ set_default_to_all_fields(param);
+
+ set_parameters(param, argc, argv);
+
+ if (!is_valid(param))
+ {
+ return -1;
+ }
+
+ return set_options(param, argc, argv);
+}
diff --git a/src/parameters/parameters.h b/src/parameters/parameters.h
new file mode 100644
index 0000000..58fc957
--- /dev/null
+++ b/src/parameters/parameters.h
@@ -0,0 +1,60 @@
+#ifndef _JH_CLI_PARAMETERS_H_
+#define _JH_CLI_PARAMETERS_H_
+
+#include "parameters_types.h"
+
+int JH_parameters_initialize
+(
+ struct JH_parameters param [const restrict static 1],
+ int const argc,
+ const char * argv [const static argc]
+);
+
+const char * JH_parameters_get_socket_name
+(
+ const struct JH_parameters param [const restrict static 1]
+);
+
+const char * JH_parameters_get_irc_server
+(
+ const struct JH_parameters param [const restrict static 1]
+);
+
+unsigned short JH_parameters_get_irc_port
+(
+ const struct JH_parameters param [const restrict static 1]
+);
+
+/* Having it as an invocation parameter makes it readable by other users on the
+ * machine.
+ */
+const char * JH_parameters_get_irc_password
+(
+ const struct JH_parameters param [const restrict static 1]
+);
+
+const char * JH_parameters_get_irc_nick
+(
+ const struct JH_parameters param [const restrict static 1]
+);
+
+const char * JH_parameters_get_irc_username
+(
+ const struct JH_parameters param [const restrict static 1]
+);
+
+const char * JH_parameters_get_irc_realname
+(
+ const struct JH_parameters param [const restrict static 1]
+);
+
+const char * JH_parameters_get_irc_channel
+(
+ const struct JH_parameters param [const restrict static 1]
+);
+
+int JH_parameters_get_irc_is_ipv6
+(
+ const struct JH_parameters param [const restrict static 1]
+);
+#endif
diff --git a/src/parameters/parameters_getters.c b/src/parameters/parameters_getters.c
new file mode 100644
index 0000000..ee2bdee
--- /dev/null
+++ b/src/parameters/parameters_getters.c
@@ -0,0 +1,73 @@
+#include "parameters.h"
+
+const char * JH_parameters_get_socket_name
+(
+ const struct JH_parameters param [const restrict static 1]
+)
+{
+ return param->socket_name;
+}
+
+const char * JH_parameters_get_irc_server
+(
+ const struct JH_parameters param [const restrict static 1]
+)
+{
+ return param->server;
+}
+
+unsigned short JH_parameters_get_irc_port
+(
+ const struct JH_parameters param [const restrict static 1]
+)
+{
+ return param->port;
+}
+
+const char * JH_parameters_get_irc_password
+(
+ const struct JH_parameters param [const restrict static 1]
+)
+{
+ return param->password;
+}
+
+const char * JH_parameters_get_irc_nick
+(
+ const struct JH_parameters param [const restrict static 1]
+)
+{
+ return param->nick;
+}
+
+const char * JH_parameters_get_irc_username
+(
+ const struct JH_parameters param [const restrict static 1]
+)
+{
+ return param->username;
+}
+
+const char * JH_parameters_get_irc_realname
+(
+ const struct JH_parameters param [const restrict static 1]
+)
+{
+ return param->realname;
+}
+
+const char * JH_parameters_get_irc_channel
+(
+ const struct JH_parameters param [const restrict static 1]
+)
+{
+ return param->channel;
+}
+
+int JH_parameters_get_irc_is_ipv6
+(
+ const struct JH_parameters param [const restrict static 1]
+)
+{
+ return param->use_ipv6;
+}
diff --git a/src/parameters/parameters_types.h b/src/parameters/parameters_types.h
new file mode 100644
index 0000000..7d8dd1c
--- /dev/null
+++ b/src/parameters/parameters_types.h
@@ -0,0 +1,21 @@
+#ifndef _JH_CLI_PARAMETERS_TYPES_H_
+#define _JH_CLI_PARAMETERS_TYPES_H_
+
+#define JH_PARAMETERS_COUNT 5
+
+struct JH_parameters
+{
+ const char * restrict socket_name;
+
+ const char * server;
+ const char * password;
+ const char * nick;
+ const char * username;
+ const char * realname;
+ const char * channel;
+ unsigned short port;
+
+ int use_ipv6;
+};
+
+#endif
diff --git a/src/pervasive.h b/src/pervasive.h
new file mode 100644
index 0000000..e69d077
--- /dev/null
+++ b/src/pervasive.h
@@ -0,0 +1,31 @@
+#ifndef _JH_PERVASIVE_H_
+#define _JH_PERVASIVE_H_
+
+#include <string.h>
+
+#define JH_PROGRAM_VERSION 1
+#define JH_PROTOCOL_VERSION 1
+
+#ifdef __FRAMA_C__
+ #define JH_RUNNING_FRAMA_C 1
+#endif
+
+#define JH_DEBUG_ALL 1
+
+#ifndef JH_DEBUG_ALL
+ #define JH_DEBUG_ALL 0
+#endif
+#ifndef JH_DEBUG_DISPLAY_IRC_MSG_EXCHANGES
+ #define JH_DEBUG_DISPLAY_IRC_MSG_EXCHANGES JH_DEBUG_ALL
+#endif
+
+#define JH__TO_STRING(x) #x
+#define JH_TO_STRING(x) JH__TO_STRING(x)
+#define JH_ISOLATE(a) do {a} while (0)
+
+/* strncmp stops at '\0' and strlen does not count '\0'. */
+#define JH_IS_PREFIX(a, b) (strncmp(a, b, strlen(a)) == 0)
+
+#define JH_STRING_EQUALS(a, b) (strcmp(a, b) == 0)
+
+#endif