diff --git a/CMakeLists.txt b/CMakeLists.txt
index 484609e..9dfa99a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,7 +15,7 @@
# License along with this program. If not, see
# .
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.1)
project(NeoComm)
set(TARGET_NAME "neocomm")
@@ -31,14 +31,18 @@ message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")
option(BUILD_SHARED_LIBS
"Whether to build a shared object instead of a static." OFF)
+find_package(Threads REQUIRED)
+
+set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+set(THREADS_PREFER_PTHREAD_FLAG TRUE)
+
include_directories(
"include/")
set(SRCS
- src/connection.c
+ src/connectivity.c
src/error.c
- src/neocomm.c
- src/nodes.c)
+ src/neocomm.c)
set(CMAKE_C_FLAGS "-std=c99 -Wall -Wextra -Werror -Wfatal-errors -Wmissing-declarations -pedantic-errors")
set(CMAKE_C_FLAGS_DEBUG "-g -O0")
@@ -53,4 +57,11 @@ else()
add_definitions("-DDEBUG")
endif()
-add_library(${TARGET_NAME} ${SRCS})
+if(BUILD_SHARED_LIBS)
+ add_library(${TARGET_NAME} SHARED ${SRCS})
+else()
+ add_library(${TARGET_NAME} STATIC ${SRCS})
+endif()
+
+target_link_libraries(${TARGET_NAME}
+ Threads::Threads)
diff --git a/README.md b/README.md
index 23ce77b..4efec9b 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,6 @@ What follows is a list roadmap of features and the (approximate) versions in whi
- [ ] Message encryption
- [ ] Private messages
- v1.0:
- - [ ] Special snowflake (Winblows) socket support
- [ ] SOCKS4a/SOCKS5 proxy support
- [ ] HTTP proxy support
- v2.0:
@@ -49,7 +48,7 @@ _There are currently no clients available._
Compiling
---------
-To build this project you will need a C99 compatible compiler ([GCC](https://gcc.gnu.org/) is recommended) and the [CMake build system](https://cmake.org/). To build run the following commands from the root directory of the project.
+To build this project you will need a C99 compatible compiler ([GCC](https://gcc.gnu.org/) is recommended), a POSIX threads compatible system, and the [CMake build system](https://cmake.org/). To build run the following commands from the root directory of the project.
```
$ cd build/
$ cmake ..
diff --git a/include/neocomm/connectivity.h b/include/neocomm/connectivity.h
new file mode 100644
index 0000000..5ee4efc
--- /dev/null
+++ b/include/neocomm/connectivity.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 Ortega Froysa, Nicolás
+ * Author: Ortega Froysa, Nicolás
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program. If not, see
+ * .
+ */
+
+#pragma once
+
+/**
+ * @file connectivity.h
+ * @brief Interfaces relating to node connections.
+ */
+
+/**
+ * @brief Simple address structure providing IP/DNS and port information.
+ */
+struct NeoComm_address {
+ const char *address; ///< IP/DNS string.
+ unsigned short port; ///< Port of address.
+};
+
+/**
+ * @brief Structure used for NeoComm nodes.
+ */
+struct NeoComm_node {
+ /// The address of the node.
+ struct NeoComm_address address;
+ /// Whether or not it is a directory node/server.
+ int directory;
+ /// Number of connections a directory has.
+ unsigned int connections;
+ /// Maximum number of connections the directory can have.
+ unsigned int max_connections;
+};
+
+
+/**
+ * @brief Initialize the directory aspect of the node.
+ *
+ * @param max_num_nodes Maximum number of nodes in the directory.
+ * @param portnum Public facing port which other nodes can connect to.
+ *
+ * @return If the operation failed then a 0 will be returned and the error can
+ * be read from the NeoComm_get_last_error function, else 1 is returned.
+ */
+int NeoComm_init_directory(const unsigned int max_num_nodes,
+ const unsigned short portnum);
+
+/**
+ * @brief Disconnect from all nodes and free memory.
+ */
+void NeoComm_shutdown_directory();
+
+/**
+ * @brief Resize the directory.
+ * @note This function only increments the size, it currently does not have
+ * the ability to decrease size.
+ *
+ * @param new_max_num_nodes The new maximum number of nodes in the directory.
+ *
+ * @return If the operation failed then a 0 will be returned and the error can
+ * be read from the NeoComm_get_last_error function, else 1 is returned.
+ */
+int NeoComm_resize_directory(const unsigned int new_max_num_nodes);
+
+/**
+ * @brief Get the current maximum number of nodes for the directory.
+ *
+ * @return The current maximum number of nodes for the directory.
+ */
+unsigned int NeoComm_get_directory_size();
+
+/**
+ * @brief Get the current number of nodes registered in the directory.
+ *
+ * @return The current number of nodes in the directory.
+ */
+unsigned int NeoComm_get_num_nodes();
+
+/**
+ * @brief Add and connect to a new node to the directory.
+ *
+ * @param addr The address of the new node to connect to.
+ *
+ * @return If the operation failed then a 0 will be returned and the error can
+ * be read from the NeoComm_get_last_error function, else 1 is returned.
+ */
+int NeoComm_add_node(const struct NeoComm_address addr);
+
+/**
+ * @brief Disconnect and remove a node from the directory.
+ *
+ * @param addr The address of the node to remove.
+ *
+ * @return If the operation failed then a 0 will be returned and the error can
+ * be read from the NeoComm_get_last_error function, else 1 is returned.
+ */
+int NeoComm_remove_node(const struct NeoComm_address addr);
+
+/**
+ * @brief Retrieve information on a specific node.
+ *
+ * @param addr The address of the node to retrieve.
+ *
+ * @return A NeoComm_node structure of the node.
+ */
+struct NeoComm_node NeoComm_get_node(const struct NeoComm_address addr);
diff --git a/include/neocomm/neocomm.h b/include/neocomm/neocomm.h
index 0ffba4a..d44eea3 100644
--- a/include/neocomm/neocomm.h
+++ b/include/neocomm/neocomm.h
@@ -19,9 +19,8 @@
#pragma once
-#include "neocomm/connection.h"
#include "neocomm/error.h"
-#include "neocomm/nodes.h"
+#include "neocomm/connectivity.h"
/**
* @file neocomm.h
diff --git a/src/connection.c b/src/connectivity.c
similarity index 56%
rename from src/connection.c
rename to src/connectivity.c
index 062d532..d50f412 100644
--- a/src/connection.c
+++ b/src/connectivity.c
@@ -17,19 +17,49 @@
* .
*/
-#include "neocomm/connection.h"
+#include "neocomm/connectivity.h"
+#include "iconnectivity.h"
-#include "internal_error.h"
+#include "ierror.h"
#include
#include
#include
#include
+#include
#include
#include
+#include
+#include
+
+/*
+ * This is an internal OS specific structure for nodes.
+ */
+struct NeoComm_directory_node {
+ int in_use;
+ struct sockaddr_in addr;
+ int sockfd;
+ pthread_t thread;
+ int open_directory;
+ unsigned int connections;
+ unsigned int max_connections;
+};
+
+static struct NeoComm_directory_node *node_list;
+static unsigned int max_nodes;
+static unsigned int num_nodes;
+
+static int run;
+static int sockfd;
+
+static pthread_t accept_thread;
+
+/*
+ * This is a protected bind function that is not accessible as a public
+ * interface.
+ */
int NeoComm_bind(const unsigned short port) {
- int sockfd;//, newsockfd;
struct sockaddr_in serv_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
@@ -100,3 +130,71 @@ int NeoComm_bind(const unsigned short port) {
return 1;
}
+
+void *NeoComm_connect_manager() {
+ while(run)
+ {
+ int cli_sockfd;
+ struct sockaddr_in cli_addr;
+ socklen_t size_cli_addr = sizeof(cli_addr);
+ cli_sockfd = accept(sockfd, (struct sockaddr*) &cli_addr,
+ &size_cli_addr);
+ if(cli_sockfd < 0)
+ {
+ NeoComm_error("Error on accept");
+ continue;
+ }
+ // TODO: Add the new connection and have it listen on a new thread.
+ }
+ pthread_exit(NULL);
+}
+
+int NeoComm_init_directory(const unsigned int max_num_nodes,
+ const unsigned short portnum) {
+ if(max_num_nodes == 0)
+ {
+ NeoComm_error("Insufficient number of nodes");
+ return 0;
+ }
+
+ if(!NeoComm_bind(portnum))
+ return 0;
+
+ node_list = calloc(max_num_nodes, sizeof(struct NeoComm_directory_node));
+ if(!node_list)
+ {
+ NeoComm_error("Failed to allocate memory to directory node list");
+ return 0;
+ }
+
+ max_nodes = max_num_nodes;
+ num_nodes = 0;
+
+ for(unsigned int i = 0; i < max_nodes; ++i)
+ node_list[i].in_use = 0;
+
+ run = 1;
+ int err = pthread_create(&accept_thread, NULL,
+ NeoComm_connect_manager, NULL);
+ if(err != 0)
+ {
+ NeoComm_error("Insufficient resources to create thread");
+ return 0;
+ }
+
+ return 1;
+}
+
+void NeoComm_shutdown_directory() {
+ run = 0;
+ void *res;
+ for(unsigned int i = 0; i < num_nodes; ++i)
+ {
+ // in case the threads are still running, we wait
+ pthread_join(node_list[i].thread, &res);
+ close(node_list[i].sockfd);
+ }
+ pthread_join(accept_thread, &res);
+ close(sockfd);
+ pthread_exit(NULL);
+}
diff --git a/src/error.c b/src/error.c
index 1b9ef38..f086907 100644
--- a/src/error.c
+++ b/src/error.c
@@ -18,7 +18,7 @@
*/
#include "neocomm/error.h"
-#include "internal_error.h"
+#include "ierror.h"
#include
diff --git a/src/globals.h b/src/globals.h
deleted file mode 100644
index 6f8820f..0000000
--- a/src/globals.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2017 Ortega Froysa, Nicolás
- * Author: Ortega Froysa, Nicolás
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program. If not, see
- * .
- */
-
-#pragma once
-
-#include "neocomm/nodes.h"
-
-// List of nodes
-extern struct NeoComm_node *node_list;
-// Maximum number of nodes
-extern unsigned int node_max;
-// Number of nodes in the list
-extern unsigned int node_count;
diff --git a/include/neocomm/connection.h b/src/iconnectivity.h
similarity index 91%
rename from include/neocomm/connection.h
rename to src/iconnectivity.h
index b0ece99..4f813b4 100644
--- a/include/neocomm/connection.h
+++ b/src/iconnectivity.h
@@ -19,6 +19,6 @@
#pragma once
-int NeoComm_bind(const unsigned short port);
+int NeoComm_bind(unsigned short portnum);
-void NeoComm_close_connections();
+void *NeoComm_connect_manager();
diff --git a/src/internal_error.h b/src/ierror.h
similarity index 100%
rename from src/internal_error.h
rename to src/ierror.h
diff --git a/src/neocomm.c b/src/neocomm.c
index 5a08fd1..00ac28a 100644
--- a/src/neocomm.c
+++ b/src/neocomm.c
@@ -18,13 +18,3 @@
*/
#include "neocomm/neocomm.h"
-
-int NeoComm_init(unsigned int max_nodes) {
- if(!NeoComm_init_nodes(max_nodes))
- return 0;
- return 1;
-}
-
-void NeoComm_shutdown() {
- NeoComm_shutdown_nodes();
-}
diff --git a/src/nodes.c b/src/nodes.c
index 8e01a06..fff1ccb 100644
--- a/src/nodes.c
+++ b/src/nodes.c
@@ -19,13 +19,19 @@
#include "neocomm/nodes.h"
-#include "globals.h"
#include "internal_error.h"
#include
#include
#include
+// List of nodes
+static struct NeoComm_node *node_list;
+// Maximum number of nodes
+static unsigned int node_max;
+// Number of nodes in the list
+static unsigned int node_count;
+
int NeoComm_init_nodes(unsigned int max_nodes) {
if(max_nodes == 0)
{