summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.travis.yml5
-rwxr-xr-xCMakeLists.txt11
-rw-r--r--INSTALL.md59
-rw-r--r--README.md9
-rw-r--r--cmake/FindSODIUM.cmake70
-rw-r--r--cmake/FindSphinx.cmake16
-rw-r--r--core/CMakeLists.txt4
-rw-r--r--core/DHT.c1004
-rw-r--r--core/DHT.h2
-rw-r--r--core/LAN_discovery.c61
-rw-r--r--core/LAN_discovery.h7
-rw-r--r--core/Lossless_UDP.c429
-rw-r--r--core/Lossless_UDP.h96
-rw-r--r--core/Messenger.c89
-rw-r--r--core/Messenger.h36
-rw-r--r--core/net_crypto.c83
-rw-r--r--core/network.c47
-rw-r--r--core/network.h17
-rw-r--r--docs/CMakeLists.txt40
-rw-r--r--docs/commands.md25
-rw-r--r--docs/commands.rst48
-rw-r--r--docs/conf.py242
-rw-r--r--docs/index.rst25
-rw-r--r--docs/install.rst129
-rw-r--r--docs/start_guide.de.rst66
-rw-r--r--docs/start_guide.rst63
-rw-r--r--docs/using_tox.md38
-rw-r--r--other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c2
-rw-r--r--start_guide.de.md40
-rw-r--r--start_guide.md38
-rw-r--r--testing/DHT_test.c12
-rw-r--r--testing/nTox.c165
-rw-r--r--testing/nTox_win32.c317
-rw-r--r--testing/nTox_win32.h7
-rw-r--r--testing/toxic/chat.c11
-rw-r--r--testing/toxic/friendlist.c1
-rw-r--r--testing/toxic/main.c7
-rw-r--r--testing/toxic/prompt.c50
39 files changed, 2285 insertions, 1087 deletions
diff --git a/.gitignore b/.gitignore
index 9969b38d..0e4e35ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
3//nacl build 3//nacl build
4nacl/build/ 4nacl/build/
5build 5build
6sodium
6 7
7CMakeCache.txt 8CMakeCache.txt
8CMakeFiles 9CMakeFiles
diff --git a/.travis.yml b/.travis.yml
index 8e71c327..a1a17f61 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,12 +21,15 @@ before_script:
21 - cd .. 21 - cd ..
22# creating librarys' links and updating cache 22# creating librarys' links and updating cache
23 - sudo ldconfig 23 - sudo ldconfig
24 24# installing sphinx, needed for documentation
25 - sudo apt-get install python-sphinx
25 26
26script: 27script:
27 - mkdir build && cd build 28 - mkdir build && cd build
28 - cmake .. 29 - cmake ..
29 - make -j3 30 - make -j3
31# build docs separately
32 - make docs
30 33
31notifications: 34notifications:
32 email: false 35 email: false
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9b7db143..07098391 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,6 +2,10 @@ cmake_minimum_required(VERSION 2.6.0)
2 2
3set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) 3set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
4 4
5if(UNIX)
6 find_package(Curses REQUIRED)
7endif()
8
5if(NOT WIN32) 9if(NOT WIN32)
6 option(USE_NACL "Use NaCl library instead of libsodium") 10 option(USE_NACL "Use NaCl library instead of libsodium")
7endif() 11endif()
@@ -29,15 +33,15 @@ if(NOT USE_NACL)
29endif() 33endif()
30 34
31macro(linkCoreLibraries exe_name) 35macro(linkCoreLibraries exe_name)
32 add_dependencies(${exe_name} core) 36 add_dependencies(${exe_name} toxcore)
33 if(WIN32) 37 if(WIN32)
34 include_directories(${CMAKE_HOME_DIRECTORY}/sodium/include/) 38 include_directories(${CMAKE_HOME_DIRECTORY}/sodium/include/)
35 target_link_libraries(${exe_name} core 39 target_link_libraries(${exe_name} toxcore
36 ${CMAKE_SOURCE_DIR}/sodium/lib/libsodium.a 40 ${CMAKE_SOURCE_DIR}/sodium/lib/libsodium.a
37 ws2_32) 41 ws2_32)
38 else() 42 else()
39 include_directories(${SODIUM_INCLUDE_DIR}) 43 include_directories(${SODIUM_INCLUDE_DIR})
40 target_link_libraries(${exe_name} core 44 target_link_libraries(${exe_name} toxcore
41 ${LINK_CRYPTO_LIBRARY}) 45 ${LINK_CRYPTO_LIBRARY})
42 46
43 endif() 47 endif()
@@ -48,3 +52,4 @@ cmake_policy(SET CMP0011 NEW)
48add_subdirectory(core) 52add_subdirectory(core)
49add_subdirectory(testing) 53add_subdirectory(testing)
50add_subdirectory(other) 54add_subdirectory(other)
55add_subdirectory(docs)
diff --git a/INSTALL.md b/INSTALL.md
index 90563790..625a9c6d 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -6,7 +6,6 @@
6 - [Homebrew](#homebrew) 6 - [Homebrew](#homebrew)
7 - [Non-Homebrew](#non-homebrew) 7 - [Non-Homebrew](#non-homebrew)
8 - [Windows](#windows) 8 - [Windows](#windows)
9- [Usage](#usage)
10 9
11<a name="installation" /> 10<a name="installation" />
12##Installation 11##Installation
@@ -19,6 +18,14 @@ Build dependencies:
19```bash 18```bash
20apt-get install build-essential libtool autotools-dev automake libconfig-dev ncurses-dev cmake checkinstall 19apt-get install build-essential libtool autotools-dev automake libconfig-dev ncurses-dev cmake checkinstall
21``` 20```
21
22On Fedora:
23
24```bash
25yum groupinstall "Development Tools"
26yum install libtool autoconf automake libconfig-devel ncurses-devel cmake
27```
28
22Note that `libconfig-dev` should be >= 1.4. 29Note that `libconfig-dev` should be >= 1.4.
23 30
24You should get and install [libsodium](https://github.com/jedisct1/libsodium): 31You should get and install [libsodium](https://github.com/jedisct1/libsodium):
@@ -32,11 +39,28 @@ sudo checkinstall --install --pkgname libsodium --pkgversion 0.4.2 --nodoc
32sudo ldconfig 39sudo ldconfig
33``` 40```
34 41
35Then clone this repo and run: 42Or if checkinstall is not easily available for your distribution (e.g. Fedora),
43this will install the libs to /usr/local/lib and the headers to /usr/local/include:
44
36```bash 45```bash
46git clone git://github.com/jedisct1/libsodium.git
47cd libsodium
48git checkout tags/0.4.2
49./autogen.sh
50./configure
51make check
52sudo make install
53```
54
55
56Then clone this repo and generate makefile:
57```bash
58git clone git://github.com/irungentoo/ProjectTox-Core.git
59cd ProjectTox-Core
37mkdir build && cd build 60mkdir build && cd build
38cmake .. 61cmake ..
39``` 62```
63Note that you should call cmake on the root [`CMakeLists.txt`](/CMakeLists.txt) file only.
40 64
41Then you can build any of the [`/testing`](/testing) and [`/other`](/other) that are currently supported on your platform by running: 65Then you can build any of the [`/testing`](/testing) and [`/other`](/other) that are currently supported on your platform by running:
42```bash 66```bash
@@ -55,21 +79,30 @@ make
55<a name="osx" /> 79<a name="osx" />
56###OS X: 80###OS X:
57 81
82You need the latest XCode with the Developer Tools (Preferences -> Downloads -> Command Line Tools).
83The following libraries are required along with libsodium and cmake for Mountain Lion and XCode 4.6.3 install libtool, automake and autoconf. You can download them with Homebrew, or install them manually.
84
85There are no binaries/executables going to /bin/ or /usr/bin/ now. Everything is compiled and ran from the inside your local branch. See [Usage](#usage) below.
86
58<a name="homebrew" /> 87<a name="homebrew" />
59####Homebrew: 88####Homebrew:
60``` 89```
61brew install libtool automake autoconf libconfig libsodium 90brew install libtool automake autoconf libconfig libsodium cmake
62cmake . 91cmake .
63make 92make
64sudo make install
65``` 93```
66 94
67<a name="non-homebrew" /> 95<a name="non-homebrew" />
68####Non-homebrew: 96####Non-homebrew:
69 97
70Much the same as Linux, remember to install the latest XCode and the developer tools (Preferences -> Downloads -> Command Line Tools). 98Grab the following packages:
71Users running Mountain Lion and the latest version of XCode (4.6.3) will also need to install libtool, automake and autoconf. 99 * http://www.gnu.org/software/libtool/
72They are easy enough to install, grab them from http://www.gnu.org/software/libtool/, http://www.gnu.org/software/autoconf/ and http://www.gnu.org/software/automake/, then follow these steps for each: 100 * http://www.gnu.org/software/autoconf/
101 * http://www.gnu.org/software/automake/
102 * http://www.cmake.org/
103 * https://github.com/jedisct1/libsodium
104
105Uncompress and install them all. Make sure to follow the README as the instructions change, but they all follow the same pattern below:
73 106
74```bash 107```bash
75./configure 108./configure
@@ -77,6 +110,13 @@ make
77sudo make install 110sudo make install
78``` 111```
79 112
113In your local TOX repository:
114
115```bash
116cmake .
117make
118```
119
80Do not install them from macports (or any dependencies for that matter) as they get shoved in the wrong directory 120Do not install them from macports (or any dependencies for that matter) as they get shoved in the wrong directory
81and make your life more annoying. 121and make your life more annoying.
82 122
@@ -102,6 +142,7 @@ Navigate in `cmd` to this repo and run:
102mkdir build && cd build 142mkdir build && cd build
103cmake -G "MinGW Makefiles" .. 143cmake -G "MinGW Makefiles" ..
104``` 144```
145Note that you should call cmake on the root [`CMakeLists.txt`](/CMakeLists.txt) file only.
105 146
106Then you can build any of the [`/testing`](/testing) and [`/other`](/other) that are currently supported on your platform by running: 147Then you can build any of the [`/testing`](/testing) and [`/other`](/other) that are currently supported on your platform by running:
107```cmd 148```cmd
@@ -117,7 +158,3 @@ Or you could just build everything that is supported on your platform by running
117mingw32-make 158mingw32-make
118``` 159```
119 160
120<a name="usage" />
121## Usage
122
123- [Start Guide](start_guide.md)
diff --git a/README.md b/README.md
index a81503a9..745fbb10 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,14 @@ With the rise of governmental monitoring programs, Tox aims to be an easy to use
7 7
8**IRC**: #tox on freenode, alternatively, you can use the [webchat](http://webchat.freenode.net/?channels=#tox).<br /> 8**IRC**: #tox on freenode, alternatively, you can use the [webchat](http://webchat.freenode.net/?channels=#tox).<br />
9**Website**: [http://tox.im](http://tox.im) 9**Website**: [http://tox.im](http://tox.im)
10**Developer Blog**: [http://dev.tox.im](http://dev.tox.im)
10 11
11**Website translations**: [see stal888's repository](https://github.com/stal888/ProjectTox-Website)<br/> 12**Website translations**: [see stal888's repository](https://github.com/stal888/ProjectTox-Website)<br/>
12**Qt GUI**: [see nurupo's repository](https://github.com/nurupo/ProjectTox-Qt-GUI) 13**Qt GUI**: [see nurupo's repository](https://github.com/nurupo/ProjectTox-Qt-GUI)
13 14
14**How to build Tox on Linux**: [YouTube video](http://www.youtube.com/watch?v=M4WXE4VKmyg)<br /> 15**How to build Tox on Linux**: [YouTube video](http://www.youtube.com/watch?v=M4WXE4VKmyg)<br />
15**How to use Tox on Windows**: [YouTube video](http://www.youtube.com/watch?v=qg_j_sDb6WQ) 16**How to use Tox on Windows**: [YouTube video](http://www.youtube.com/watch?v=qg_j_sDb6WQ)<br />
17**For Mac OSX read** [INSTALL.md](INSTALL.md)
16 18
17### Objectives: 19### Objectives:
18 20
@@ -34,18 +36,19 @@ Keep everything really simple.
34- [ ] Streaming media 36- [ ] Streaming media
35- [ ] ??? 37- [ ] ???
36 38
37For further information, check our [To-do list](https://github.com/irungentoo/ProjectTox-Core/wiki/TODO) 39For further information, check our [To-do list](http://wiki.tox.im/index.php/TODO)
38 40
39### Why are you doing this? There are already a bunch of free skype alternatives. 41### Why are you doing this? There are already a bunch of free skype alternatives.
40The goal of this project is to create a configuration-free P2P skype 42The goal of this project is to create a configuration-free P2P skype
41replacement. Configuration-free means that the user will simply have to open the program and 43replacement. Configuration-free means that the user will simply have to open the program and
42without any account configuration will be capable of adding people to his 44without any account configuration will be capable of adding people to his
43friends list and start conversing with them. There are many so called skype replacements and all of them are either hard to 45friends list and start conversing with them. There are many so-called skype replacements and all of them are either hard to
44configure for the normal user or suffer from being way too centralized. 46configure for the normal user or suffer from being way too centralized.
45 47
46### Documentation: 48### Documentation:
47 49
48- [Installation](/INSTALL.md) 50- [Installation](/INSTALL.md)
51- [Commands](/docs/commands.rst)
49- [DHT Protocol](https://github.com/irungentoo/ProjectTox-Core/wiki/DHT)<br /> 52- [DHT Protocol](https://github.com/irungentoo/ProjectTox-Core/wiki/DHT)<br />
50- [Lossless UDP Protocol](https://github.com/irungentoo/ProjectTox-Core/wiki/Lossless-UDP)<br /> 53- [Lossless UDP Protocol](https://github.com/irungentoo/ProjectTox-Core/wiki/Lossless-UDP)<br />
51- [Crypto](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto)<br /> 54- [Crypto](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto)<br />
diff --git a/cmake/FindSODIUM.cmake b/cmake/FindSODIUM.cmake
index ffb6a1f7..fd6206ff 100644
--- a/cmake/FindSODIUM.cmake
+++ b/cmake/FindSODIUM.cmake
@@ -1,15 +1,67 @@
1# Find SODIUM 1# - Try to find SODIUM
2# Once done this will define
2# 3#
3# SODIUM_INCLUDE_DIR 4# SODIUM_ROOT_DIR - Set this variable to the root installation of CMocka
4# SODIUM_LIBRARY
5# SODIUM_FOUND
6# 5#
6# Read-Only variables:
7# SODIUM_FOUND - system has SODIUM
8# SODIUM_INCLUDE_DIR - the SODIUM include directory
9# SODIUM_LIBRARIES - Link these to use SODIUM
10# SODIUM_DEFINITIONS - Compiler switches required for using SODIUM
11#
12#=============================================================================
13# Copyright (c) 2013 Andreas Schneider <asn@cryptomilk.org>
14#
15# Distributed under the OSI-approved BSD License (the "License");
16# see accompanying file Copyright.txt for details.
17#
18# This software is distributed WITHOUT ANY WARRANTY; without even the
19# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20# See the License for more information.
21#=============================================================================
22#
23
24set(_SODIUM_ROOT_HINTS
25)
26
27set(_SODIUM_ROOT_PATHS
28 "$ENV{PROGRAMFILES}/sodium"
29)
30
31find_path(SODIUM_ROOT_DIR
32 NAMES
33 include/cmocka.h
34 HINTS
35 ${_SODIUM_ROOT_HINTS}
36 PATHS
37 ${_SODIUM_ROOT_PATHS}
38)
39mark_as_advanced(SODIUM_ROOT_DIR)
40
41find_path(SODIUM_INCLUDE_DIR
42 NAMES
43 sodium.h
44 PATHS
45 ${SODIUM_ROOT_DIR}/include
46)
47
48find_library(SODIUM_LIBRARY
49 NAMES
50 sodium
51 PATHS
52 ${SODIUM_ROOT_DIR}/lib
53)
7 54
8FIND_PATH(SODIUM_INCLUDE_DIR NAMES sodium.h) 55if (SODIUM_LIBRARY)
56 set(SODIUM_LIBRARIES
57 ${SODIUM_LIBRARIES}
58 ${SODIUM_LIBRARY}
59 )
60endif (SODIUM_LIBRARY)
9 61
10FIND_LIBRARY(SODIUM_LIBRARY NAMES sodium) 62include(FindPackageHandleStandardArgs)
63find_package_handle_standard_args(SODIUM DEFAULT_MSG SODIUM_LIBRARIES SODIUM_INCLUDE_DIR)
11 64
12INCLUDE(FindPackageHandleStandardArgs) 65# show the SODIUM_INCLUDE_DIR and SODIUM_LIBRARIES variables only in the advanced view
13FIND_PACKAGE_HANDLE_STANDARD_ARGS(SODIUM DEFAULT_MSG SODIUM_LIBRARY SODIUM_INCLUDE_DIR) 66mark_as_advanced(SODIUM_INCLUDE_DIR SODIUM_LIBRARIES)
14 67
15MARK_AS_ADVANCED(SODIUM_INCLUDE_DIR SODIUM_LIBRARY)
diff --git a/cmake/FindSphinx.cmake b/cmake/FindSphinx.cmake
new file mode 100644
index 00000000..833bfd4d
--- /dev/null
+++ b/cmake/FindSphinx.cmake
@@ -0,0 +1,16 @@
1find_program(SPHINX_EXECUTABLE NAMES sphinx-build
2 HINTS
3 $ENV{SPHINX_DIR}
4 PATH_SUFFIXES bin
5 DOC "Sphinx documentation generator"
6)
7
8include(FindPackageHandleStandardArgs)
9
10find_package_handle_standard_args(Sphinx DEFAULT_MSG
11 SPHINX_EXECUTABLE
12)
13
14mark_as_advanced(
15 SPHINX_EXECUTABLE
16)
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index 44ae980c..36acb6cf 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -1,5 +1,5 @@
1cmake_minimum_required(VERSION 2.6.0) 1cmake_minimum_required(VERSION 2.6.0)
2project(core C) 2project(toxcore C)
3 3
4if(WIN32) 4if(WIN32)
5 include_directories(${CMAKE_HOME_DIRECTORY}/sodium/include/) 5 include_directories(${CMAKE_HOME_DIRECTORY}/sodium/include/)
@@ -16,4 +16,4 @@ set(core_sources
16 LAN_discovery.c 16 LAN_discovery.c
17 Messenger.c) 17 Messenger.c)
18 18
19add_library(core ${core_sources}) 19add_library(toxcore SHARED ${core_sources})
diff --git a/core/DHT.c b/core/DHT.c
index 5039f710..5d5910e0 100644
--- a/core/DHT.c
+++ b/core/DHT.c
@@ -21,102 +21,156 @@
21 * 21 *
22 */ 22 */
23 23
24#include "DHT.h" 24/*----------------------------------------------------------------------------------*/
25 25
26typedef struct { 26#include "DHT.h"
27 uint8_t client_id[CLIENT_ID_SIZE];
28 IP_Port ip_port;
29 uint32_t timestamp;
30 uint32_t last_pinged;
31 IP_Port ret_ip_port;/* The ip_port returned by this node for the friend
32 (for nodes in friends_list) or us (for nodes in close_clientlist) */
33 uint32_t ret_timestamp;
34} Client_data;
35 27
36/* maximum number of clients stored per friend. */ 28/* maximum number of clients stored per friend. */
37#define MAX_FRIEND_CLIENTS 8 29#define MAX_FRIEND_CLIENTS 8
38 30
39typedef struct { 31/* A list of the clients mathematically closest to ours. */
40 uint8_t client_id[CLIENT_ID_SIZE]; 32#define LCLIENT_LIST 32
41 Client_data client_list[MAX_FRIEND_CLIENTS]; 33
42 uint32_t lastgetnode; /* time at which the last get_nodes request was sent. */ 34/* The list of ip ports along with the ping_id of what we sent them and a timestamp */
43 35#define LPING_ARRAY 256
44 /*Symetric NAT hole punching stuff*/ 36
45 uint8_t hole_punching; /*0 if not hole punching, 1 if currently hole punching */ 37#define LSEND_NODES_ARRAY LPING_ARRAY/2
46 uint32_t punching_index; 38
47 uint32_t punching_timestamp; 39/* the number of seconds for a non responsive node to become bad. */
48 uint32_t recvNATping_timestamp; 40#define BAD_NODE_TIMEOUT 70
49 uint64_t NATping_id; 41
50 uint32_t NATping_timestamp; 42/* the max number of nodes to send with send nodes. */
51} Friend; 43#define MAX_SENT_NODES 8
44
45/* ping timeout in seconds */
46#define PING_TIMEOUT 5
47
48/* The timeout after which a node is discarded completely. */
49#define Kill_NODE_TIMEOUT 300
50
51/* ping interval in seconds for each node in our lists. */
52#define PING_INTERVAL 60
53
54/* ping interval in seconds for each random sending of a get nodes request. */
55#define GET_NODE_INTERVAL 10
56
57#define MAX_PUNCHING_PORTS 32
58
59/*Interval in seconds between punching attempts*/
60#define PUNCH_INTERVAL 10
61
62/*----------------------------------------------------------------------------------*/
52 63
53typedef struct { 64typedef struct {
54 uint8_t client_id[CLIENT_ID_SIZE]; 65 uint8_t client_id[CLIENT_ID_SIZE];
55 IP_Port ip_port; 66 IP_Port ip_port;
56} Node_format; 67 uint64_t timestamp;
68 uint64_t last_pinged;
69
70 /* Returned by this node. Either our friend or us */
71 IP_Port ret_ip_port;
72 uint64_t ret_timestamp;
73} Client_data;
57 74
58typedef struct { 75typedef struct {
59 IP_Port ip_port; 76 uint8_t client_id[CLIENT_ID_SIZE];
60 uint64_t ping_id; 77 Client_data client_list[MAX_FRIEND_CLIENTS];
61 uint32_t timestamp;
62 78
63} Pinged; 79 /* time at which the last get_nodes request was sent. */
80 uint64_t lastgetnode;
64 81
65/* Our client id/public key */ 82 /* Symetric NAT hole punching stuff */
66uint8_t self_public_key[CLIENT_ID_SIZE];
67uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
68 83
69/* TODO: Move these out of here and put them into the .c file. 84 /* 1 if currently hole punching, otherwise 0 */
70 A list of the clients mathematically closest to ours. */ 85 uint8_t hole_punching;
71#define LCLIENT_LIST 32 86 uint32_t punching_index;
72static Client_data close_clientlist[LCLIENT_LIST]; 87 uint64_t punching_timestamp;
88 uint64_t recvNATping_timestamp;
89 uint64_t NATping_id;
90 uint64_t NATping_timestamp;
91} Friend;
73 92
74static Friend * friends_list; 93typedef struct {
75static uint16_t num_friends; 94 uint8_t client_id[CLIENT_ID_SIZE];
95 IP_Port ip_port;
96} Node_format;
76 97
77/* The list of ip ports along with the ping_id of what we sent them and a timestamp */ 98typedef struct {
78#define LPING_ARRAY 256 99 IP_Port ip_port;
100 uint64_t ping_id;
101 uint64_t timestamp;
102} Pinged;
79 103
80static Pinged pings[LPING_ARRAY]; 104/*----------------------------------------------------------------------------------*/
81 105
82#define LSEND_NODES_ARRAY LPING_ARRAY/2 106 /* Our client id/public key */
107uint8_t self_public_key[CLIENT_ID_SIZE];
108uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
109static Client_data close_clientlist[LCLIENT_LIST];
110static Friend * friends_list;
111static uint16_t num_friends;
112static Pinged pings[LPING_ARRAY];
113static Pinged send_nodes[LSEND_NODES_ARRAY];
83 114
84static Pinged send_nodes[LSEND_NODES_ARRAY]; 115/*----------------------------------------------------------------------------------*/
85 116
86/* Compares client_id1 and client_id2 with client_id 117/* Compares client_id1 and client_id2 with client_id
87 return 0 if both are same distance 118 * return 0 if both are same distance
88 return 1 if client_id1 is closer 119 * return 1 if client_id1 is closer
89 return 2 if client_id2 is closer */ 120 * return 2 if client_id2 is closer
90int id_closest(uint8_t * client_id, uint8_t * client_id1, uint8_t * client_id2) /* tested */ 121 */
122int id_closest(uint8_t * id, uint8_t * id1, uint8_t * id2)
91{ 123{
92 uint32_t i; 124 size_t i;
125 uint8_t distance1, distance2;
126
93 for(i = 0; i < CLIENT_ID_SIZE; ++i) { 127 for(i = 0; i < CLIENT_ID_SIZE; ++i) {
94 if(abs(client_id[i] ^ client_id1[i]) < abs(client_id[i] ^ client_id2[i])) 128
129 distance1 = abs(id[i] ^ id1[i]);
130 distance2 = abs(id[i] ^ id2[i]);
131
132 if(distance1 < distance2)
95 return 1; 133 return 1;
96 else if(abs(client_id[i] ^ client_id1[i]) > abs(client_id[i] ^ client_id2[i])) 134 if(distance1 > distance2)
97 return 2; 135 return 2;
98 } 136 }
99 return 0; 137 return 0;
100} 138}
101 139
140int ipport_equal(IP_Port a, IP_Port b)
141{
142 return (a.ip.i == b.ip.i) && (a.port == b.port);
143}
144
145int id_equal(uint8_t* a, uint8_t* b)
146{
147 return memcmp(a, b, CLIENT_ID_SIZE) == 0;
148}
149
150int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout)
151{
152 return timestamp + timeout <= time_now;
153}
154
102/* check if client with client_id is already in list of length length. 155/* check if client with client_id is already in list of length length.
103 if it is set it's corresponding timestamp to current time. 156 * if it is then set its corresponding timestamp to current time.
104 if the id is already in the list with a different ip_port, update it. 157 * if the id is already in the list with a different ip_port, update it.
105 return True(1) or False(0) 158 * return True(1) or False(0)
106 TODO: maybe optimize this. */ 159 *
160 * TODO: maybe optimize this.
161 */
107int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port) 162int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port)
108{ 163{
109 uint32_t i; 164 uint32_t i;
110 uint32_t temp_time = unix_time(); 165 uint64_t temp_time = unix_time();
111 166
112 for(i = 0; i < length; ++i) { 167 for(i = 0; i < length; ++i) {
113 /*If ip_port is assigned to a different client_id replace it*/ 168 /*If ip_port is assigned to a different client_id replace it*/
114 if(list[i].ip_port.ip.i == ip_port.ip.i && 169 if(ipport_equal(list[i].ip_port, ip_port)) {
115 list[i].ip_port.port == ip_port.port) {
116 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 170 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
117 } 171 }
118 172
119 if(memcmp(list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { 173 if(id_equal(list[i].client_id, client_id)) {
120 /* Refresh the client timestamp. */ 174 /* Refresh the client timestamp. */
121 list[i].timestamp = temp_time; 175 list[i].timestamp = temp_time;
122 list[i].ip_port.ip.i = ip_port.ip.i; 176 list[i].ip_port.ip.i = ip_port.ip.i;
@@ -125,88 +179,138 @@ int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_
125 } 179 }
126 } 180 }
127 return 0; 181 return 0;
128
129} 182}
130 183
131/* check if client with client_id is already in node format list of length length. 184/* check if client with client_id is already in node format list of length length.
132 return True(1) or False(0) */ 185 * return True(1) or False(0)
186 */
133int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id) 187int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id)
134{ 188{
135 uint32_t i; 189 uint32_t i;
136 for(i = 0; i < length; ++i) 190
137 if(memcmp(list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) 191 for(i = 0; i < length; ++i) {
192 if(id_equal(list[i].client_id, client_id))
138 return 1; 193 return 1;
194 }
195
139 return 0; 196 return 0;
140} 197}
141 198
142/*Return the friend number from the client_id 199/* Returns the friend number from the client_id, or -1 if a failure occurs
143 Return -1 if failure, number of friend if success*/ 200 */
144static int friend_number(uint8_t * client_id) 201static int friend_number(uint8_t * client_id)
145{ 202{
146 uint32_t i; 203 uint32_t i;
147 for(i = 0; i < num_friends; ++i) 204
148 if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) /* Equal */ 205 for(i = 0; i < num_friends; ++i) {
206 if(id_equal(friends_list[i].client_id, client_id))
149 return i; 207 return i;
208 }
209
150 return -1; 210 return -1;
151} 211}
152 212
153/* the number of seconds for a non responsive node to become bad. */
154#define BAD_NODE_TIMEOUT 70
155/* the max number of nodes to send with send nodes. */
156#define MAX_SENT_NODES 8
157
158/* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request: 213/* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request:
159 put them in the nodes_list and return how many were found. 214 * put them in the nodes_list and return how many were found.
160 TODO: Make this function much more efficient. */ 215 *
216 * TODO: For the love of based Allah make this function cleaner and much more efficient.
217 */
161int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) 218int get_close_nodes(uint8_t * client_id, Node_format * nodes_list)
162{ 219{
163 uint32_t i, j, k; 220 uint32_t i, j, k;
164 int num_nodes=0; 221 uint64_t temp_time = unix_time();
165 uint32_t temp_time = unix_time(); 222 int num_nodes = 0, closest, tout, inlist;
166 for(i = 0; i < LCLIENT_LIST; ++i) 223
167 if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time && 224 for (i = 0; i < LCLIENT_LIST; ++i) {
168 !client_in_nodelist(nodes_list, MAX_SENT_NODES,close_clientlist[i].client_id)) { 225 tout = is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT);
169 /* if node is good and not already in list. */ 226 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, close_clientlist[i].client_id);
227
228 /* if node isn't good or is already in list. */
229 if(tout || inlist)
230 continue;
231
232 if(num_nodes < MAX_SENT_NODES) {
233
234 memcpy( nodes_list[num_nodes].client_id,
235 close_clientlist[i].client_id,
236 CLIENT_ID_SIZE );
237
238 nodes_list[num_nodes].ip_port = close_clientlist[i].ip_port;
239 num_nodes++;
240
241 } else {
242
243 for(j = 0; j < MAX_SENT_NODES; ++j) {
244 closest = id_closest( client_id,
245 nodes_list[j].client_id,
246 close_clientlist[i].client_id );
247 if(closest == 2) {
248 memcpy( nodes_list[j].client_id,
249 close_clientlist[i].client_id,
250 CLIENT_ID_SIZE);
251
252 nodes_list[j].ip_port = close_clientlist[i].ip_port;
253 break;
254 }
255 }
256 }
257 }
258
259 for(i = 0; i < num_friends; ++i) {
260 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
261
262 tout = is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT);
263 inlist = client_in_nodelist( nodes_list,
264 MAX_SENT_NODES,
265 friends_list[i].client_list[j].client_id);
266
267 /* if node isn't good or is already in list. */
268 if(tout || inlist)
269 continue;
270
170 if(num_nodes < MAX_SENT_NODES) { 271 if(num_nodes < MAX_SENT_NODES) {
171 memcpy(nodes_list[num_nodes].client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE); 272
172 nodes_list[num_nodes].ip_port = close_clientlist[i].ip_port; 273 memcpy( nodes_list[num_nodes].client_id,
274 friends_list[i].client_list[j].client_id,
275 CLIENT_ID_SIZE);
276
277 nodes_list[num_nodes].ip_port = friends_list[i].client_list[j].ip_port;
173 num_nodes++; 278 num_nodes++;
174 } else for(j = 0; j < MAX_SENT_NODES; ++j) 279 } else {
175 if(id_closest(client_id, nodes_list[j].client_id, close_clientlist[i].client_id) == 2) { 280 for(k = 0; k < MAX_SENT_NODES; ++k) {
176 memcpy(nodes_list[j].client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE); 281
177 nodes_list[j].ip_port = close_clientlist[i].ip_port; 282 closest = id_closest( client_id,
283 nodes_list[k].client_id,
284 friends_list[i].client_list[j].client_id );
285 if(closest == 2) {
286 memcpy( nodes_list[k].client_id,
287 friends_list[i].client_list[j].client_id,
288 CLIENT_ID_SIZE );
289
290 nodes_list[k].ip_port = friends_list[i].client_list[j].ip_port;
178 break; 291 break;
179 } 292 }
180 } 293 }
181
182 for(i = 0; i < num_friends; ++i)
183 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j)
184 if(friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time &&
185 !client_in_nodelist(nodes_list, MAX_SENT_NODES,friends_list[i].client_list[j].client_id)) {
186 /* if node is good and not already in list. */
187 if(num_nodes < MAX_SENT_NODES) {
188 memcpy(nodes_list[num_nodes].client_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE);
189 nodes_list[num_nodes].ip_port = friends_list[i].client_list[j].ip_port;
190 num_nodes++;
191 } else for(k = 0; k < MAX_SENT_NODES; ++k)
192 if(id_closest(client_id, nodes_list[k].client_id, friends_list[i].client_list[j].client_id) == 2) {
193 memcpy(nodes_list[k].client_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE);
194 nodes_list[k].ip_port = friends_list[i].client_list[j].ip_port;
195 break;
196 }
197 } 294 }
295 }
296 }
198 return num_nodes; 297 return num_nodes;
199} 298}
200 299
201/* replace first bad (or empty) node with this one 300/* replace first bad (or empty) node with this one
202 return 0 if successful 301 * return 0 if successful
203 return 1 if not (list contains no bad nodes) */ 302 * return 1 if not (list contains no bad nodes)
204int replace_bad(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port) /* tested */ 303 */
304int replace_bad( Client_data * list,
305 uint32_t length,
306 uint8_t * client_id,
307 IP_Port ip_port )
205{ 308{
206 uint32_t i; 309 uint32_t i;
207 uint32_t temp_time = unix_time(); 310 uint64_t temp_time = unix_time();
208 for(i = 0; i < length; ++i) 311 for(i = 0; i < length; ++i) {
209 if(list[i].timestamp + BAD_NODE_TIMEOUT < temp_time) { /* if node is bad. */ 312 /* if node is bad */
313 if(is_timeout(temp_time, list[i].timestamp, BAD_NODE_TIMEOUT)) {
210 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 314 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
211 list[i].ip_port = ip_port; 315 list[i].ip_port = ip_port;
212 list[i].timestamp = temp_time; 316 list[i].timestamp = temp_time;
@@ -215,15 +319,20 @@ int replace_bad(Client_data * list, uint32_t length, uint8_t * client_id, IP_Por
215 list[i].ret_timestamp = 0; 319 list[i].ret_timestamp = 0;
216 return 0; 320 return 0;
217 } 321 }
322 }
218 323
219 return 1; 324 return 1;
220} 325}
221 326
222/* replace the first good node that is further to the comp_client_id than that of the client_id in the list */ 327/* replace the first good node that is further to the comp_client_id than that of the client_id in the list */
223int replace_good(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port, uint8_t * comp_client_id) 328int replace_good( Client_data * list,
329 uint32_t length,
330 uint8_t * client_id,
331 IP_Port ip_port,
332 uint8_t * comp_client_id )
224{ 333{
225 uint32_t i; 334 uint32_t i;
226 uint32_t temp_time = unix_time(); 335 uint64_t temp_time = unix_time();
227 336
228 for(i = 0; i < length; ++i) 337 for(i = 0; i < length; ++i)
229 if(id_closest(comp_client_id, list[i].client_id, client_id) == 2) { 338 if(id_closest(comp_client_id, list[i].client_id, client_id) == 2) {
@@ -239,75 +348,109 @@ int replace_good(Client_data * list, uint32_t length, uint8_t * client_id, IP_Po
239 return 1; 348 return 1;
240} 349}
241 350
242/* Attempt to add client with ip_port and client_id to the friends client list and close_clientlist */ 351/* Attempt to add client with ip_port and client_id to the friends client list
352 * and close_clientlist
353 */
243void addto_lists(IP_Port ip_port, uint8_t * client_id) 354void addto_lists(IP_Port ip_port, uint8_t * client_id)
244{ 355{
245 uint32_t i; 356 uint32_t i;
246 357
247 /* NOTE: current behavior if there are two clients with the same id is to replace the first ip by the second. */ 358 /* NOTE: current behavior if there are two clients with the same id is
248 if(!client_in_list(close_clientlist, LCLIENT_LIST, client_id, ip_port)) 359 * to replace the first ip by the second.
249 if(replace_bad(close_clientlist, LCLIENT_LIST, client_id, ip_port)) 360 */
361 if (!client_in_list(close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
362 if (replace_bad(close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
250 /* if we can't replace bad nodes we try replacing good ones */ 363 /* if we can't replace bad nodes we try replacing good ones */
251 replace_good(close_clientlist, LCLIENT_LIST, client_id, ip_port, self_public_key); 364 replace_good( close_clientlist,
365 LCLIENT_LIST,
366 client_id,
367 ip_port,
368 self_public_key );
369 }
370 }
371
372 for (i = 0; i < num_friends; ++i) {
373 if (!client_in_list( friends_list[i].client_list,
374 MAX_FRIEND_CLIENTS,
375 client_id,
376 ip_port )) {
252 377
253 for(i = 0; i < num_friends; ++i) 378 if (replace_bad( friends_list[i].client_list,
254 if(!client_in_list(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port)) 379 MAX_FRIEND_CLIENTS,
255 if(replace_bad(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port)) 380 client_id,
381 ip_port )) {
256 /* if we can't replace bad nodes we try replacing good ones. */ 382 /* if we can't replace bad nodes we try replacing good ones. */
257 replace_good(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port, friends_list[i].client_id); 383 replace_good( friends_list[i].client_list,
384 MAX_FRIEND_CLIENTS,
385 client_id,
386 ip_port,
387 friends_list[i].client_id );
388 }
389 }
390 }
258} 391}
259 392
260/* If client_id is a friend or us, update ret_ip_port 393/* If client_id is a friend or us, update ret_ip_port
261 nodeclient_id is the id of the node that sent us this info */ 394 * nodeclient_id is the id of the node that sent us this info
395 */
262void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient_id) 396void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient_id)
263{ 397{
264 uint32_t i, j; 398 uint32_t i, j;
265 uint32_t temp_time = unix_time(); 399 uint64_t temp_time = unix_time();
266 if(memcmp(client_id, self_public_key, CLIENT_ID_SIZE) == 0) { 400
267 for(i = 0; i < LCLIENT_LIST; ++i) 401 if (id_equal(client_id, self_public_key)) {
268 if(memcmp(nodeclient_id, close_clientlist[i].client_id, CLIENT_ID_SIZE) == 0) { 402
403 for (i = 0; i < LCLIENT_LIST; ++i) {
404 if (id_equal(nodeclient_id, close_clientlist[i].client_id)) {
269 close_clientlist[i].ret_ip_port = ip_port; 405 close_clientlist[i].ret_ip_port = ip_port;
270 close_clientlist[i].ret_timestamp = temp_time; 406 close_clientlist[i].ret_timestamp = temp_time;
271 return; 407 return;
272 } 408 }
273 } else 409 }
274 for(i = 0; i < num_friends; ++i) 410
275 if(memcmp(client_id, friends_list[i].client_id, CLIENT_ID_SIZE) == 0) 411 } else {
276 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 412
277 if(memcmp(nodeclient_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE) == 0) { 413 for (i = 0; i < num_friends; ++i) {
414 if (id_equal(client_id, friends_list[i].client_id)) {
415
416 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
417 if (id_equal(nodeclient_id, friends_list[i].client_list[j].client_id)) {
278 friends_list[i].client_list[j].ret_ip_port = ip_port; 418 friends_list[i].client_list[j].ret_ip_port = ip_port;
279 friends_list[i].client_list[j].ret_timestamp = temp_time; 419 friends_list[i].client_list[j].ret_timestamp = temp_time;
280 return; 420 return;
281 } 421 }
282} 422 }
423 }
424 }
283 425
284/* ping timeout in seconds */ 426 }
285#define PING_TIMEOUT 5 427}
286 428
287/* check if we are currently pinging an ip_port and/or a ping_id 429/* check if we are currently pinging an ip_port and/or a ping_id variables with
288 variables with values of zero will not be checked. 430 * values of zero will not be checked. If we are already, return 1 else return 0
289 if we are already, return 1 431 *
290 else return 0 432 * TODO: optimize this
291TODO: optimize this */ 433 */
292int is_pinging(IP_Port ip_port, uint64_t ping_id) 434int is_pinging(IP_Port ip_port, uint64_t ping_id)
293{ 435{
294 uint32_t i; 436 uint32_t i;
295 uint8_t pinging; 437 uint8_t pinging;
296 uint32_t temp_time = unix_time(); 438 uint64_t temp_time = unix_time();
297 439
298 for(i = 0; i < LPING_ARRAY; ++i ) 440 for (i = 0; i < LPING_ARRAY; ++i ) {
299 if((pings[i].timestamp + PING_TIMEOUT) > temp_time) { 441 if (!is_timeout(temp_time, pings[i].timestamp, PING_TIMEOUT)) {
300 pinging = 0; 442 pinging = 0;
301 if(ip_port.ip.i != 0) 443
302 if(pings[i].ip_port.ip.i == ip_port.ip.i && 444 if (ip_port.ip.i != 0 && ipport_equal(pings[i].ip_port, ip_port))
303 pings[i].ip_port.port == ip_port.port)
304 ++pinging;
305 if(ping_id != 0)
306 if(pings[i].ping_id == ping_id)
307 ++pinging; 445 ++pinging;
308 if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) 446
447 if (ping_id != 0 && pings[i].ping_id == ping_id)
448 ++pinging;
449
450 if (pinging == ((ping_id != 0) + (ip_port.ip.i != 0)))
309 return 1; 451 return 1;
310 } 452 }
453 }
311 454
312 return 0; 455 return 0;
313} 456}
@@ -317,44 +460,48 @@ int is_gettingnodes(IP_Port ip_port, uint64_t ping_id)
317{ 460{
318 uint32_t i; 461 uint32_t i;
319 uint8_t pinging; 462 uint8_t pinging;
320 uint32_t temp_time = unix_time(); 463 uint64_t temp_time = unix_time();
321 464
322 for(i = 0; i < LSEND_NODES_ARRAY; ++i ) 465 for(i = 0; i < LSEND_NODES_ARRAY; ++i ) {
323 if((send_nodes[i].timestamp + PING_TIMEOUT) > temp_time) { 466 if(!is_timeout(temp_time, send_nodes[i].timestamp, PING_TIMEOUT)) {
324 pinging = 0; 467 pinging = 0;
325 if(ip_port.ip.i != 0) 468
326 if(send_nodes[i].ip_port.ip.i == ip_port.ip.i && 469 if(ip_port.ip.i != 0 && ipport_equal(send_nodes[i].ip_port, ip_port))
327 send_nodes[i].ip_port.port == ip_port.port)
328 ++pinging; 470 ++pinging;
329 if(ping_id != 0) 471
330 if(send_nodes[i].ping_id == ping_id) 472 if(ping_id != 0 && send_nodes[i].ping_id == ping_id)
331 ++pinging; 473 ++pinging;
474
332 if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) 475 if(pinging == (ping_id != 0) + (ip_port.ip.i != 0))
333 return 1; 476 return 1;
334
335 } 477 }
478 }
336 479
337 return 0; 480 return 0;
338} 481}
339 482
340/* Add a new ping request to the list of ping requests 483/* Add a new ping request to the list of ping requests
341 returns the ping_id to put in the ping request 484 * returns the ping_id to put in the ping request
342 returns 0 if problem. 485 * returns 0 if problem.
343 TODO: optimize this */ 486 *
487 * TODO: optimize this
488 */
344uint64_t add_pinging(IP_Port ip_port) 489uint64_t add_pinging(IP_Port ip_port)
345{ 490{
346 uint32_t i, j; 491 uint32_t i, j;
347 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); 492 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int();
348 uint32_t temp_time = unix_time(); 493 uint64_t temp_time = unix_time();
349 494
350 for(i = 0; i < PING_TIMEOUT; ++i ) 495 for(i = 0; i < PING_TIMEOUT; ++i ) {
351 for(j = 0; j < LPING_ARRAY; ++j ) 496 for(j = 0; j < LPING_ARRAY; ++j ) {
352 if((pings[j].timestamp + PING_TIMEOUT - i) < temp_time) { 497 if(is_timeout(temp_time, pings[j].timestamp, PING_TIMEOUT - i)) {
353 pings[j].timestamp = temp_time; 498 pings[j].timestamp = temp_time;
354 pings[j].ip_port = ip_port; 499 pings[j].ip_port = ip_port;
355 pings[j].ping_id = ping_id; 500 pings[j].ping_id = ping_id;
356 return ping_id; 501 return ping_id;
357 } 502 }
503 }
504 }
358 505
359 return 0; 506 return 0;
360} 507}
@@ -364,28 +511,29 @@ uint64_t add_gettingnodes(IP_Port ip_port)
364{ 511{
365 uint32_t i, j; 512 uint32_t i, j;
366 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); 513 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int();
367 uint32_t temp_time = unix_time(); 514 uint64_t temp_time = unix_time();
368 515
369 for(i = 0; i < PING_TIMEOUT; ++i ) 516 for(i = 0; i < PING_TIMEOUT; ++i ) {
370 for(j = 0; j < LSEND_NODES_ARRAY; ++j ) 517 for(j = 0; j < LSEND_NODES_ARRAY; ++j ) {
371 if((send_nodes[j].timestamp + PING_TIMEOUT - i) < temp_time) { 518 if(is_timeout(temp_time, send_nodes[j].timestamp, PING_TIMEOUT - i)) {
372 send_nodes[j].timestamp = temp_time; 519 send_nodes[j].timestamp = temp_time;
373 send_nodes[j].ip_port = ip_port; 520 send_nodes[j].ip_port = ip_port;
374 send_nodes[j].ping_id = ping_id; 521 send_nodes[j].ping_id = ping_id;
375 return ping_id; 522 return ping_id;
376 } 523 }
524 }
525 }
377 526
378 return 0; 527 return 0;
379} 528}
380 529
381/* send a ping request 530/* send a ping request, only works if none has been sent to that ip/port
382 Ping request only works if none has been sent to that ip/port in the last 5 seconds. */ 531 * in the last 5 seconds.
532 */
383static int pingreq(IP_Port ip_port, uint8_t * public_key) 533static int pingreq(IP_Port ip_port, uint8_t * public_key)
384{ 534{
385 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ 535 /* check if packet is gonna be sent to ourself */
386 return 1; 536 if(id_equal(public_key, self_public_key) || is_pinging(ip_port, 0))
387
388 if(is_pinging(ip_port, 0))
389 return 1; 537 return 1;
390 538
391 uint64_t ping_id = add_pinging(ip_port); 539 uint64_t ping_id = add_pinging(ip_port);
@@ -397,9 +545,16 @@ static int pingreq(IP_Port ip_port, uint8_t * public_key)
397 uint8_t nonce[crypto_box_NONCEBYTES]; 545 uint8_t nonce[crypto_box_NONCEBYTES];
398 random_nonce(nonce); 546 random_nonce(nonce);
399 547
400 int len = encrypt_data(public_key, self_secret_key, nonce, (uint8_t *)&ping_id, sizeof(ping_id), encrypt); 548 int len = encrypt_data( public_key,
549 self_secret_key,
550 nonce,
551 (uint8_t *)&ping_id,
552 sizeof(ping_id),
553 encrypt );
554
401 if(len != sizeof(ping_id) + ENCRYPTION_PADDING) 555 if(len != sizeof(ping_id) + ENCRYPTION_PADDING)
402 return -1; 556 return -1;
557
403 data[0] = 0; 558 data[0] = 0;
404 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 559 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
405 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 560 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
@@ -412,7 +567,7 @@ static int pingreq(IP_Port ip_port, uint8_t * public_key)
412static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id) 567static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id)
413{ 568{
414 /* check if packet is gonna be sent to ourself */ 569 /* check if packet is gonna be sent to ourself */
415 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) 570 if(id_equal(public_key, self_public_key))
416 return 1; 571 return 1;
417 572
418 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING]; 573 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING];
@@ -420,9 +575,15 @@ static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id)
420 uint8_t nonce[crypto_box_NONCEBYTES]; 575 uint8_t nonce[crypto_box_NONCEBYTES];
421 random_nonce(nonce); 576 random_nonce(nonce);
422 577
423 int len = encrypt_data(public_key, self_secret_key, nonce, (uint8_t *)&ping_id, sizeof(ping_id), encrypt); 578 int len = encrypt_data( public_key,
579 self_secret_key, nonce,
580 (uint8_t *)&ping_id,
581 sizeof(ping_id),
582 encrypt );
583
424 if(len != sizeof(ping_id) + ENCRYPTION_PADDING) 584 if(len != sizeof(ping_id) + ENCRYPTION_PADDING)
425 return -1; 585 return -1;
586
426 data[0] = 1; 587 data[0] = 1;
427 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 588 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
428 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 589 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
@@ -435,10 +596,7 @@ static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id)
435static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) 596static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id)
436{ 597{
437 /* check if packet is gonna be sent to ourself */ 598 /* check if packet is gonna be sent to ourself */
438 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) 599 if(id_equal(public_key, self_public_key) || is_gettingnodes(ip_port, 0))
439 return 1;
440
441 if(is_gettingnodes(ip_port, 0))
442 return 1; 600 return 1;
443 601
444 uint64_t ping_id = add_gettingnodes(ip_port); 602 uint64_t ping_id = add_gettingnodes(ip_port);
@@ -455,21 +613,29 @@ static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id)
455 memcpy(plain, &ping_id, sizeof(ping_id)); 613 memcpy(plain, &ping_id, sizeof(ping_id));
456 memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE); 614 memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE);
457 615
458 int len = encrypt_data(public_key, self_secret_key, nonce, plain, sizeof(ping_id) + CLIENT_ID_SIZE, encrypt); 616 int len = encrypt_data( public_key,
617 self_secret_key,
618 nonce,
619 plain,
620 sizeof(ping_id) + CLIENT_ID_SIZE,
621 encrypt );
459 622
460 if(len != sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) 623 if(len != sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING)
461 return -1; 624 return -1;
625
462 data[0] = 2; 626 data[0] = 2;
463 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 627 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
464 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 628 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
465 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 629 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
630
466 return sendpacket(ip_port, data, sizeof(data)); 631 return sendpacket(ip_port, data, sizeof(data));
467} 632}
468 633
469/* send a send nodes response */ 634/* send a send nodes response */
470static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, uint64_t ping_id) 635static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, uint64_t ping_id)
471{ 636{
472 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ 637 /* check if packet is gonna be sent to ourself */
638 if(id_equal(public_key, self_public_key))
473 return 1; 639 return 1;
474 640
475 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 641 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
@@ -489,8 +655,12 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id,
489 memcpy(plain, &ping_id, sizeof(ping_id)); 655 memcpy(plain, &ping_id, sizeof(ping_id));
490 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); 656 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format));
491 657
492 int len = encrypt_data(public_key, self_secret_key, nonce, plain, 658 int len = encrypt_data( public_key,
493 sizeof(ping_id) + num_nodes * sizeof(Node_format), encrypt); 659 self_secret_key,
660 nonce,
661 plain,
662 sizeof(ping_id) + num_nodes * sizeof(Node_format),
663 encrypt );
494 664
495 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) 665 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING)
496 return -1; 666 return -1;
@@ -503,26 +673,30 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id,
503 return sendpacket(ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); 673 return sendpacket(ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
504} 674}
505 675
506/* Packet handling functions 676/* Packet handling functions, one to handle each types of packets we receive
507 One to handle each types of packets we receive 677 * Returns 0 if handled correctly, 1 if packet is bad.
508 return 0 if handled correctly, 1 if packet is bad. */ 678 */
509int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source) 679int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source)
510{ 680{
511 uint64_t ping_id; 681 uint64_t ping_id;
512 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING) 682 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING)
513 return 1; 683 return 1;
684
514 /* check if packet is from ourself. */ 685 /* check if packet is from ourself. */
515 if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) 686 if(id_equal(packet + 1, self_public_key))
516 return 1; 687 return 1;
517 688
518 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 689 int len = decrypt_data( packet + 1,
519 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 690 self_secret_key,
520 sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id); 691 packet + 1 + CLIENT_ID_SIZE,
692 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
693 sizeof(ping_id) + ENCRYPTION_PADDING,
694 (uint8_t *)&ping_id );
695
521 if(len != sizeof(ping_id)) 696 if(len != sizeof(ping_id))
522 return 1; 697 return 1;
523 698
524 pingres(source, packet + 1, ping_id); 699 pingres(source, packet + 1, ping_id);
525
526 pingreq(source, packet + 1); /* TODO: make this smarter? */ 700 pingreq(source, packet + 1); /* TODO: make this smarter? */
527 701
528 return 0; 702 return 0;
@@ -533,12 +707,18 @@ int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source)
533 uint64_t ping_id; 707 uint64_t ping_id;
534 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING) 708 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING)
535 return 1; 709 return 1;
536 if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is from ourself. */ 710
711 /* check if packet is from ourself. */
712 if(id_equal(packet + 1, self_public_key))
537 return 1; 713 return 1;
538 714
539 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 715 int len = decrypt_data( packet + 1,
540 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 716 self_secret_key,
541 sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id); 717 packet + 1 + CLIENT_ID_SIZE,
718 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
719 sizeof(ping_id) + ENCRYPTION_PADDING,
720 (uint8_t *)&ping_id );
721
542 if(len != sizeof(ping_id)) 722 if(len != sizeof(ping_id))
543 return 1; 723 return 1;
544 724
@@ -547,25 +727,30 @@ int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source)
547 return 0; 727 return 0;
548 } 728 }
549 return 1; 729 return 1;
550
551} 730}
552 731
553int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source) 732int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
554{ 733{
555 uint64_t ping_id; 734 uint64_t ping_id;
556 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) 735
736 if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES
737 + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING ))
557 return 1; 738 return 1;
739
558 /* check if packet is from ourself. */ 740 /* check if packet is from ourself. */
559 if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) 741 if (id_equal(packet + 1, self_public_key))
560 return 1; 742 return 1;
561 743
562 uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; 744 uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE];
563 745
564 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 746 int len = decrypt_data( packet + 1,
565 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 747 self_secret_key,
566 sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING, plain); 748 packet + 1 + CLIENT_ID_SIZE,
749 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
750 sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING,
751 plain );
567 752
568 if(len != sizeof(ping_id) + CLIENT_ID_SIZE) 753 if (len != sizeof(ping_id) + CLIENT_ID_SIZE)
569 return 1; 754 return 1;
570 755
571 memcpy(&ping_id, plain, sizeof(ping_id)); 756 memcpy(&ping_id, plain, sizeof(ping_id));
@@ -574,29 +759,28 @@ int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
574 pingreq(source, packet + 1); /* TODO: make this smarter? */ 759 pingreq(source, packet + 1); /* TODO: make this smarter? */
575 760
576 return 0; 761 return 0;
577
578} 762}
579 763
580int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source) 764int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source)
581{ 765{
582 uint64_t ping_id; 766 uint64_t ping_id;
583 /* TODO: make this more readable */ 767 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
584 if(length > (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 768 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
585 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING) || 769
586 (length - (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 770 if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) ||
587 + ENCRYPTION_PADDING)) % (sizeof(Node_format)) != 0 || 771 ((length - cid_size) % sizeof(Node_format)) != 0 ||
588 length < 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 772 (length < cid_size + sizeof(Node_format)))
589 + sizeof(Node_format) + ENCRYPTION_PADDING) {
590 return 1; 773 return 1;
591 }
592 uint32_t num_nodes = (length - (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES
593 + sizeof(ping_id) + ENCRYPTION_PADDING)) / sizeof(Node_format);
594 774
775 uint32_t num_nodes = (length - cid_size) / sizeof(Node_format);
595 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 776 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES];
596 777
597 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 778 int len = decrypt_data(
598 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 779 packet + 1,
599 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain); 780 self_secret_key,
781 packet + 1 + CLIENT_ID_SIZE,
782 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
783 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain );
600 784
601 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) 785 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format))
602 return 1; 786 return 1;
@@ -619,18 +803,20 @@ int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source)
619 return 0; 803 return 0;
620} 804}
621 805
622/* END of packet handling functions */ 806/*----------------------------------------------------------------------------------*/
807/*------------------------END of packet handling functions--------------------------*/
623 808
624int DHT_addfriend(uint8_t * client_id) 809int DHT_addfriend(uint8_t * client_id)
625{ 810{
626 Friend * temp; 811 Friend * temp;
627 temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1)); 812 temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1));
628 if(temp == NULL) 813 if (temp == NULL)
629 return 1; 814 return 1;
630 815
631 friends_list = temp; 816 friends_list = temp;
632 memset(&friends_list[num_friends], 0, sizeof(Friend)); 817 memset(&friends_list[num_friends], 0, sizeof(Friend));
633 memcpy(friends_list[num_friends].client_id, client_id, CLIENT_ID_SIZE); 818 memcpy(friends_list[num_friends].client_id, client_id, CLIENT_ID_SIZE);
819
634 friends_list[num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); 820 friends_list[num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int();
635 ++num_friends; 821 ++num_friends;
636 return 0; 822 return 0;
@@ -640,17 +826,25 @@ int DHT_delfriend(uint8_t * client_id)
640{ 826{
641 uint32_t i; 827 uint32_t i;
642 Friend * temp; 828 Friend * temp;
643 for(i = 0; i < num_friends; ++i) 829 for (i = 0; i < num_friends; ++i) {
644 /* Equal */ 830 /* Equal */
645 if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { 831 if (id_equal(friends_list[i].client_id, client_id)) {
646 --num_friends; 832 --num_friends;
647 if(num_friends != i) 833
648 memcpy(friends_list[i].client_id, friends_list[num_friends].client_id, CLIENT_ID_SIZE); 834 if (num_friends != i) {
835 memcpy( friends_list[i].client_id,
836 friends_list[num_friends].client_id,
837 CLIENT_ID_SIZE );
838 }
839
649 temp = realloc(friends_list, sizeof(Friend) * (num_friends)); 840 temp = realloc(friends_list, sizeof(Friend) * (num_friends));
650 if(temp != NULL) 841 if (temp == NULL)
651 friends_list = temp; 842 return 1;
843
844 friends_list = temp;
652 return 0; 845 return 0;
653 } 846 }
847 }
654 848
655 return 1; 849 return 1;
656} 850}
@@ -659,95 +853,94 @@ int DHT_delfriend(uint8_t * client_id)
659IP_Port DHT_getfriendip(uint8_t * client_id) 853IP_Port DHT_getfriendip(uint8_t * client_id)
660{ 854{
661 uint32_t i, j; 855 uint32_t i, j;
856 uint64_t temp_time = unix_time();
662 IP_Port empty = {{{0}}, 0}; 857 IP_Port empty = {{{0}}, 0};
663 uint32_t temp_time = unix_time(); 858
664 for(i = 0; i < num_friends; ++i) 859 for (i = 0; i < num_friends; ++i) {
665 /* Equal */ 860 /* Equal */
666 if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { 861 if (id_equal(friends_list[i].client_id, client_id)) {
667 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 862 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
668 if(memcmp(friends_list[i].client_list[j].client_id, client_id, CLIENT_ID_SIZE) == 0 && 863 if (id_equal(friends_list[i].client_list[j].client_id, client_id) && !is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT))
669 friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time)
670 return friends_list[i].client_list[j].ip_port; 864 return friends_list[i].client_list[j].ip_port;
671 865 }
672 return empty; 866 return empty;
673 } 867 }
868 }
674 empty.ip.i = 1; 869 empty.ip.i = 1;
675 return empty; 870 return empty;
676
677} 871}
678 872
679/* The timeout after which a node is discarded completely. */ 873/* Ping each client in the "friends" list every 60 seconds. Send a get nodes request
680#define Kill_NODE_TIMEOUT 300 874 * every 20 seconds to a random good node for each "friend" in our "friends" list.
681 875 */
682/* ping interval in seconds for each node in our lists. */
683#define PING_INTERVAL 60
684
685/* ping interval in seconds for each random sending of a get nodes request. */
686#define GET_NODE_INTERVAL 10
687
688/* Ping each client in the "friends" list every 60 seconds.
689 Send a get nodes request every 20 seconds to a random good node for each "friend" in our "friends" list. */
690void doDHTFriends() 876void doDHTFriends()
691{ 877{
692 uint32_t i, j; 878 uint32_t i, j;
693 uint32_t temp_time = unix_time(); 879 uint64_t temp_time = unix_time();
694 uint32_t rand_node; 880 uint32_t rand_node;
695 uint32_t index[MAX_FRIEND_CLIENTS]; 881 uint32_t index[MAX_FRIEND_CLIENTS];
696 882
697 for(i = 0; i < num_friends; ++i) { 883 for (i = 0; i < num_friends; ++i) {
698 uint32_t num_nodes = 0; 884 uint32_t num_nodes = 0;
699 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 885 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
700 if(friends_list[i].client_list[j].timestamp + Kill_NODE_TIMEOUT > temp_time) { /* if node is not dead. */ 886 /* if node is not dead. */
701 if((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { 887 if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) {
702 pingreq(friends_list[i].client_list[j].ip_port, friends_list[i].client_list[j].client_id); 888 if ((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) {
889 pingreq( friends_list[i].client_list[j].ip_port,
890 friends_list[i].client_list[j].client_id );
703 friends_list[i].client_list[j].last_pinged = temp_time; 891 friends_list[i].client_list[j].last_pinged = temp_time;
704 } 892 }
705 if(friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time) { /* if node is good. */ 893 /* if node is good. */
894 if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) {
706 index[num_nodes] = j; 895 index[num_nodes] = j;
707 ++num_nodes; 896 ++num_nodes;
708 } 897 }
709 } 898 }
899 }
710 if(friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { 900 if(friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) {
711 rand_node = rand() % num_nodes; 901 rand_node = rand() % num_nodes;
712 getnodes(friends_list[i].client_list[index[rand_node]].ip_port, 902 getnodes( friends_list[i].client_list[index[rand_node]].ip_port,
713 friends_list[i].client_list[index[rand_node]].client_id, 903 friends_list[i].client_list[index[rand_node]].client_id,
714 friends_list[i].client_id); 904 friends_list[i].client_id );
715 friends_list[i].lastgetnode = temp_time; 905 friends_list[i].lastgetnode = temp_time;
716 } 906 }
717 } 907 }
718} 908}
719 909
720static uint32_t close_lastgetnodes; 910static uint64_t close_lastgetnodes;
721 911
722/* Ping each client in the close nodes list every 60 seconds. 912/* Ping each client in the close nodes list every 60 seconds.
723 Send a get nodes request every 20 seconds to a random good node in the list. */ 913 * Send a get nodes request every 20 seconds to a random good node in the list.
724void doClose() /* tested */ 914 */
915void doClose()
725{ 916{
726 uint32_t i; 917 uint32_t i;
727 uint32_t temp_time = unix_time(); 918 uint64_t temp_time = unix_time();
728 uint32_t num_nodes = 0; 919 uint32_t num_nodes = 0;
729 uint32_t rand_node; 920 uint32_t rand_node;
730 uint32_t index[LCLIENT_LIST]; 921 uint32_t index[LCLIENT_LIST];
731 922
732 for(i = 0; i < LCLIENT_LIST; ++i) 923 for (i = 0; i < LCLIENT_LIST; ++i) {
733 /* if node is not dead. */ 924 /* if node is not dead. */
734 if(close_clientlist[i].timestamp + Kill_NODE_TIMEOUT > temp_time) { 925 if (!is_timeout(temp_time, close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) {
735 if((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { 926 if ((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) {
736 pingreq(close_clientlist[i].ip_port, close_clientlist[i].client_id); 927 pingreq( close_clientlist[i].ip_port,
928 close_clientlist[i].client_id );
737 close_clientlist[i].last_pinged = temp_time; 929 close_clientlist[i].last_pinged = temp_time;
738 } 930 }
739 /* if node is good. */ 931 /* if node is good. */
740 if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) { 932 if (!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) {
741 index[num_nodes] = i; 933 index[num_nodes] = i;
742 ++num_nodes; 934 ++num_nodes;
743 } 935 }
744 } 936 }
937 }
745 938
746 if(close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { 939 if (close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) {
747 rand_node = rand() % num_nodes; 940 rand_node = rand() % num_nodes;
748 getnodes(close_clientlist[index[rand_node]].ip_port, 941 getnodes( close_clientlist[index[rand_node]].ip_port,
749 close_clientlist[index[rand_node]].client_id, 942 close_clientlist[index[rand_node]].client_id,
750 self_public_key); 943 self_public_key );
751 close_lastgetnodes = temp_time; 944 close_lastgetnodes = temp_time;
752 } 945 }
753} 946}
@@ -758,123 +951,155 @@ void DHT_bootstrap(IP_Port ip_port, uint8_t * public_key)
758} 951}
759 952
760/* send the given packet to node with client_id 953/* send the given packet to node with client_id
761 returns -1 if failure */ 954 * returns -1 if failure
955 */
762int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length) 956int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length)
763{ 957{
764 uint32_t i; 958 uint32_t i;
765 for(i = 0; i < LCLIENT_LIST; ++i) 959
766 if(memcmp(client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE) == 0) 960 for (i = 0; i < LCLIENT_LIST; ++i) {
961 if (id_equal(client_id, close_clientlist[i].client_id))
767 return sendpacket(close_clientlist[i].ip_port, packet, length); 962 return sendpacket(close_clientlist[i].ip_port, packet, length);
963 }
964
768 return -1; 965 return -1;
769} 966}
770 967
771/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist 968/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist
772 ip_portlist must be at least MAX_FRIEND_CLIENTS big 969 * ip_portlist must be at least MAX_FRIEND_CLIENTS big
773 returns the number of ips returned 970 * returns the number of ips returned
774 return 0 if we are connected to friend or if no ips were found. 971 * return 0 if we are connected to friend or if no ips were found.
775 returns -1 if no such friend*/ 972 * returns -1 if no such friend
973 */
776static int friend_iplist(IP_Port * ip_portlist, uint16_t friend_num) 974static int friend_iplist(IP_Port * ip_portlist, uint16_t friend_num)
777{ 975{
778 int num_ips = 0; 976 int num_ips = 0;
779 uint32_t i; 977 uint32_t i;
780 uint32_t temp_time = unix_time(); 978 uint64_t temp_time = unix_time();
781 if(friend_num >= num_friends) 979
980 if (friend_num >= num_friends)
782 return -1; 981 return -1;
783 for(i = 0; i < MAX_FRIEND_CLIENTS; ++i) 982
983 Friend * friend = &friends_list[friend_num];
984 Client_data * client;
985
986 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
987 client = &friend->client_list[i];
988
784 /*If ip is not zero and node is good */ 989 /*If ip is not zero and node is good */
785 if(friends_list[friend_num].client_list[i].ret_ip_port.ip.i != 0 && 990 if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
786 friends_list[friend_num].client_list[i].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) { 991
787 if(memcmp(friends_list[friend_num].client_list[i].client_id, friends_list[friend_num].client_id, CLIENT_ID_SIZE) == 0 ) 992 if (id_equal(client->client_id, friend->client_id))
788 return 0; 993 return 0;
789 ip_portlist[num_ips] = friends_list[friend_num].client_list[i].ret_ip_port; 994
995 ip_portlist[num_ips] = client->ret_ip_port;
790 ++num_ips; 996 ++num_ips;
791 } 997 }
998 }
792 return num_ips; 999 return num_ips;
793} 1000}
794 1001
795/* Send the following packet to everyone who tells us they are connected to friend_id 1002/* Send the following packet to everyone who tells us they are connected to friend_id
796 returns the number of nodes it sent the packet to */ 1003 * returns the number of nodes it sent the packet to
1004 */
797int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) 1005int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length)
798{ 1006{
799 uint32_t i, j; 1007 int num = friend_number(friend_id);
800 uint32_t sent = 0; 1008 if (num == -1)
801 uint32_t temp_time = unix_time(); 1009 return 0;
802 for(i = 0; i < num_friends; ++i) 1010
803 /* Equal */ 1011 uint32_t i, sent = 0;
804 if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) { 1012 uint64_t temp_time = unix_time();
805 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 1013 Friend * friend = &friends_list[num];
806 /*If ip is not zero and node is good */ 1014 Client_data * client;
807 if(friends_list[i].client_list[j].ret_ip_port.ip.i != 0 && 1015
808 friends_list[i].client_list[j].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) 1016 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
809 if(sendpacket(friends_list[i].client_list[j].ip_port, packet, length) == length) 1017 client = &friend->client_list[i];
810 ++sent; 1018
811 return sent; 1019 /*If ip is not zero and node is good */
1020 if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
1021
1022 if (sendpacket(client->ip_port, packet, length) == length)
1023 ++sent;
812 } 1024 }
813 return 0; 1025 }
1026 return sent;
814} 1027}
815 1028
816/* Send the following packet to one random person who tells us they are connected to friend_id 1029/* Send the following packet to one random person who tells us they are connected to friend_id
817 returns the number of nodes it sent the packet to */ 1030* returns the number of nodes it sent the packet to
1031*/
818int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) 1032int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length)
819{ 1033{
820 int num = friend_number(friend_id); 1034 int num = friend_number(friend_id);
821 if(num == -1) 1035 if (num == -1)
822 return 0; 1036 return 0;
823 1037
1038 Friend * friend = &friends_list[num];
1039 Client_data * client;
1040
824 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1041 IP_Port ip_list[MAX_FRIEND_CLIENTS];
825 int n = 0; 1042 int n = 0;
826 uint32_t i; 1043 uint32_t i;
827 uint32_t temp_time = unix_time(); 1044 uint64_t temp_time = unix_time();
828 for(i = 0; i < MAX_FRIEND_CLIENTS; ++i) 1045
1046 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1047 client = &friend->client_list[i];
1048
829 /*If ip is not zero and node is good */ 1049 /*If ip is not zero and node is good */
830 if(friends_list[num].client_list[i].ret_ip_port.ip.i != 0 && 1050 if(client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
831 friends_list[num].client_list[i].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) { 1051 ip_list[n] = client->ip_port;
832 ip_list[n] = friends_list[num].client_list[i].ip_port;
833 ++n; 1052 ++n;
834 } 1053 }
835 if(n < 1) 1054 }
1055 if (n < 1)
836 return 0; 1056 return 0;
837 if(sendpacket(ip_list[rand() % n], packet, length) == length) 1057 if (sendpacket(ip_list[rand() % n], packet, length) == length)
838 return 1; 1058 return 1;
839 return 0; 1059 return 0;
840} 1060}
841 1061
842/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist 1062/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist
843 ip_portlist must be at least MAX_FRIEND_CLIENTS big 1063 * ip_portlist must be at least MAX_FRIEND_CLIENTS big
844 returns the number of ips returned 1064 * returns the number of ips returned
845 return 0 if we are connected to friend or if no ips were found. 1065 * return 0 if we are connected to friend or if no ips were found.
846 returns -1 if no such friend*/ 1066 * returns -1 if no such friend
1067 */
847int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id) 1068int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id)
848{ 1069{
849
850 uint32_t i; 1070 uint32_t i;
851 for(i = 0; i < num_friends; ++i) 1071 for (i = 0; i < num_friends; ++i) {
852 /* Equal */ 1072 /* Equal */
853 if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) 1073 if (id_equal(friends_list[i].client_id, friend_id))
854 return friend_iplist(ip_portlist, i); 1074 return friend_iplist(ip_portlist, i);
1075 }
855 return -1; 1076 return -1;
856} 1077}
857 1078
858/*BEGINNING OF NAT PUNCHING FUNCTIONS*/ 1079/*----------------------------------------------------------------------------------*/
1080/*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/
859 1081
860int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) 1082int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type)
861{ 1083{
862 uint8_t data[sizeof(uint64_t) + 1]; 1084 uint8_t data[sizeof(uint64_t) + 1];
1085 uint8_t packet[MAX_DATA_SIZE];
1086
1087 int num = 0;
1088
863 data[0] = type; 1089 data[0] = type;
864 memcpy(data + 1, &ping_id, sizeof(uint64_t)); 1090 memcpy(data + 1, &ping_id, sizeof(uint64_t));
1091 /* 254 is NAT ping request packet id */
1092 int len = create_request(packet, public_key, data, sizeof(uint64_t) + 1, 254);
865 1093
866 uint8_t packet[MAX_DATA_SIZE]; 1094 if (len == -1)
867 int len = create_request(packet, public_key, data, sizeof(uint64_t) + 1, 254); /* 254 is NAT ping request packet id */
868 if(len == -1)
869 return -1; 1095 return -1;
870 1096
871 int num = 0; 1097 if (type == 0) /*If packet is request use many people to route it*/
1098 num = route_tofriend(public_key, packet, len);
1099 else if (type == 1) /*If packet is response use only one person to route it*/
1100 num = routeone_tofriend(public_key, packet, len);
872 1101
873 if(type == 0) 1102 if (num == 0)
874 num = route_tofriend(public_key, packet, len);/*If packet is request use many people to route it*/
875 else if(type == 1)
876 num = routeone_tofriend(public_key, packet, len);/*If packet is response use only one person to route it*/
877 if(num == 0)
878 return -1; 1103 return -1;
879 return num; 1104 return num;
880} 1105}
@@ -882,45 +1107,54 @@ int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type)
882/* Handle a recieved ping request for */ 1107/* Handle a recieved ping request for */
883int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source) 1108int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source)
884{ 1109{
885 if(length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && 1110 if (length < crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING
886 length > MAX_DATA_SIZE + ENCRYPTION_PADDING) 1111 && length > MAX_DATA_SIZE + ENCRYPTION_PADDING)
887 return 1; 1112 return 1;
1113
888 /* check if request is for us. */ 1114 /* check if request is for us. */
889 if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { 1115 if (id_equal(packet + 1, self_public_key)) {
890 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 1116 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
891 uint8_t data[MAX_DATA_SIZE]; 1117 uint8_t data[MAX_DATA_SIZE];
1118
892 int len = handle_request(public_key, data, packet, length); 1119 int len = handle_request(public_key, data, packet, length);
893 if(len != sizeof(uint64_t) + 1) 1120 if (len != sizeof(uint64_t) + 1)
894 return 1; 1121 return 1;
1122
895 uint64_t ping_id; 1123 uint64_t ping_id;
896 memcpy(&ping_id, data + 1, sizeof(uint64_t)); 1124 memcpy(&ping_id, data + 1, sizeof(uint64_t));
897 1125
898 int friendnumber = friend_number(public_key); 1126 int friendnumber = friend_number(public_key);
899 if(friendnumber == -1) 1127 if (friendnumber == -1)
900 return 1; 1128 return 1;
901 1129
902 if(data[0] == 0) { 1130 Friend * friend = &friends_list[friendnumber];
903 send_NATping(public_key, ping_id, 1); /*1 is reply*/ 1131
904 friends_list[friendnumber].recvNATping_timestamp = unix_time(); 1132 if (data[0] == 0) {
1133 /* 1 is reply */
1134 send_NATping(public_key, ping_id, 1);
1135 friend->recvNATping_timestamp = unix_time();
905 return 0; 1136 return 0;
906 } else if (data[0] == 1) 1137 } else if (data[0] == 1) {
907 if(friends_list[friendnumber].NATping_id == ping_id) { 1138 if (friend->NATping_id == ping_id) {
908 friends_list[friendnumber].NATping_id = ((uint64_t)random_int() << 32) + random_int(); 1139 friend->NATping_id = ((uint64_t)random_int() << 32) + random_int();
909 friends_list[friendnumber].hole_punching = 1; 1140 friend->hole_punching = 1;
910 return 0; 1141 return 0;
911 } 1142 }
1143 }
912 return 1; 1144 return 1;
913 } 1145 }
1146
914 /* if request is not for us, try routing it. */ 1147 /* if request is not for us, try routing it. */
915 else if(route_packet(packet + 1, packet, length) == length) 1148 route_packet(packet + 1, packet, length);
916 return 0; 1149
917 return 0; 1150 return 0;
918} 1151}
919 1152
920/*Get the most common ip in the ip_portlist 1153/* Get the most common ip in the ip_portlist
921 Only return ip if it appears in list min_num or more 1154 * Only return ip if it appears in list min_num or more
922 len must not be bigger than MAX_FRIEND_CLIENTS 1155 * len must not be bigger than MAX_FRIEND_CLIENTS
923 return ip of 0 if failure */ 1156 * return ip of 0 if failure
1157 */
924static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num) 1158static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num)
925{ 1159{
926 IP zero = {{0}}; 1160 IP zero = {{0}};
@@ -929,40 +1163,45 @@ static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num)
929 1163
930 uint32_t i, j; 1164 uint32_t i, j;
931 uint16_t numbers[MAX_FRIEND_CLIENTS] = {0}; 1165 uint16_t numbers[MAX_FRIEND_CLIENTS] = {0};
1166
932 for(i = 0; i < len; ++i) { 1167 for(i = 0; i < len; ++i) {
933 for(j = 0; j < len; ++j) 1168 for(j = 0; j < len; ++j) {
934 if(ip_portlist[i].ip.i == ip_portlist[j].ip.i) 1169 if(ip_portlist[i].ip.i == ip_portlist[j].ip.i)
935 ++numbers[i]; 1170 ++numbers[i];
1171 }
936 if(numbers[i] >= min_num) 1172 if(numbers[i] >= min_num)
937 return ip_portlist[i].ip; 1173 return ip_portlist[i].ip;
938 } 1174 }
939 return zero; 1175 return zero;
940} 1176}
941 1177
942/*Return all the ports for one ip in a list 1178/* Return all the ports for one ip in a list
943 portlist must be at least len long 1179 * portlist must be at least len long
944 where len is the length of ip_portlist 1180 * where len is the length of ip_portlist
945 returns the number of ports and puts the list of ports in portlist*/ 1181 * returns the number of ports and puts the list of ports in portlist
1182 */
946static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip) 1183static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip)
947{ 1184{
948 uint32_t i; 1185 uint32_t i;
949 uint16_t num = 0; 1186 uint16_t num = 0;
950 for(i = 0; i < len; ++i) 1187
1188 for(i = 0; i < len; ++i) {
951 if(ip_portlist[i].ip.i == ip.i) { 1189 if(ip_portlist[i].ip.i == ip.i) {
952 portlist[num] = ntohs(ip_portlist[i].port); 1190 portlist[num] = ntohs(ip_portlist[i].port);
953 ++num; 1191 ++num;
954 } 1192 }
1193 }
955 return num; 1194 return num;
956} 1195}
957 1196
958#define MAX_PUNCHING_PORTS 32
959
960static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t friend_num) 1197static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t friend_num)
961{ 1198{
962 if(numports > MAX_FRIEND_CLIENTS || numports == 0) 1199 if(numports > MAX_FRIEND_CLIENTS || numports == 0)
963 return; 1200 return;
1201
964 uint32_t i; 1202 uint32_t i;
965 uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; 1203 uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS;
1204
966 for(i = friends_list[friend_num].punching_index; i != top; i++) { 1205 for(i = friends_list[friend_num].punching_index; i != top; i++) {
967 /*TODO: improve port guessing algorithm*/ 1206 /*TODO: improve port guessing algorithm*/
968 uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1); 1207 uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1);
@@ -972,30 +1211,29 @@ static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t
972 friends_list[friend_num].punching_index = i; 1211 friends_list[friend_num].punching_index = i;
973} 1212}
974 1213
975/*Interval in seconds between punching attempts*/
976#define PUNCH_INTERVAL 10
977
978static void doNAT() 1214static void doNAT()
979{ 1215{
980 uint32_t i; 1216 uint32_t i;
981 uint32_t temp_time = unix_time(); 1217 uint64_t temp_time = unix_time();
982 for(i = 0; i < num_friends; ++i) { 1218
1219 for (i = 0; i < num_friends; ++i) {
983 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1220 IP_Port ip_list[MAX_FRIEND_CLIENTS];
984 int num = friend_iplist(ip_list, i); 1221 int num = friend_iplist(ip_list, i);
985 /*If we are connected to friend or if friend is not online don't try to hole punch with him*/
986 if(num < MAX_FRIEND_CLIENTS/2)
987 continue;
988 1222
1223 /*If already connected or friend is not online don't try to hole punch*/
1224 if (num < MAX_FRIEND_CLIENTS/2)
1225 continue;
989 1226
990 if(friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { 1227 if (friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) {
991 send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/ 1228 send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/
992 friends_list[i].NATping_timestamp = temp_time; 1229 friends_list[i].NATping_timestamp = temp_time;
993 } 1230 }
994 if(friends_list[i].hole_punching == 1 && 1231 if (friends_list[i].hole_punching == 1 &&
995 friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && 1232 friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time &&
996 friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL*2 >= temp_time) { 1233 friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL*2 >= temp_time) {
1234
997 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2); 1235 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2);
998 if(ip.i == 0) 1236 if (ip.i == 0)
999 continue; 1237 continue;
1000 1238
1001 uint16_t port_list[MAX_FRIEND_CLIENTS]; 1239 uint16_t port_list[MAX_FRIEND_CLIENTS];
@@ -1008,7 +1246,8 @@ static void doNAT()
1008 } 1246 }
1009} 1247}
1010 1248
1011/*END OF NAT PUNCHING FUNCTIONS*/ 1249/*----------------------------------------------------------------------------------*/
1250/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/
1012 1251
1013int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) 1252int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
1014{ 1253{
@@ -1057,17 +1296,22 @@ void DHT_save(uint8_t * data)
1057} 1296}
1058 1297
1059/* load the DHT from data of size size; 1298/* load the DHT from data of size size;
1060 return -1 if failure 1299 * return -1 if failure
1061 return 0 if success */ 1300 * return 0 if success
1301 */
1062int DHT_load(uint8_t * data, uint32_t size) 1302int DHT_load(uint8_t * data, uint32_t size)
1063{ 1303{
1064 if(size < sizeof(close_clientlist)) 1304 if(size < sizeof(close_clientlist))
1065 return -1; 1305 return -1;
1306
1066 if((size - sizeof(close_clientlist)) % sizeof(Friend) != 0) 1307 if((size - sizeof(close_clientlist)) % sizeof(Friend) != 0)
1067 return -1; 1308 return -1;
1309
1068 uint32_t i, j; 1310 uint32_t i, j;
1069 /* uint32_t temp_time = unix_time(); */
1070 uint16_t temp; 1311 uint16_t temp;
1312 /* uint64_t temp_time = unix_time(); */
1313
1314 Client_data * client;
1071 1315
1072 temp = (size - sizeof(close_clientlist))/sizeof(Friend); 1316 temp = (size - sizeof(close_clientlist))/sizeof(Friend);
1073 1317
@@ -1076,29 +1320,35 @@ int DHT_load(uint8_t * data, uint32_t size)
1076 1320
1077 for(i = 0; i < temp; ++i) { 1321 for(i = 0; i < temp; ++i) {
1078 DHT_addfriend(tempfriends_list[i].client_id); 1322 DHT_addfriend(tempfriends_list[i].client_id);
1079 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 1323
1080 if(tempfriends_list[i].client_list[j].timestamp != 0) { 1324 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1081 getnodes(tempfriends_list[i].client_list[j].ip_port, 1325 client = &tempfriends_list[i].client_list[j];
1082 tempfriends_list[i].client_list[j].client_id, tempfriends_list[i].client_id); 1326 if(client->timestamp != 0)
1083 } 1327 getnodes(client->ip_port, client->client_id, tempfriends_list[i].client_id);
1328 }
1084 } 1329 }
1085 } 1330 }
1086 Client_data * tempclose_clientlist = (Client_data *)data; 1331 Client_data * tempclose_clientlist = (Client_data *)data;
1087 1332
1088 for(i = 0; i < LCLIENT_LIST; ++i) 1333 for(i = 0; i < LCLIENT_LIST; ++i) {
1089 if(tempclose_clientlist[i].timestamp != 0) 1334 if(tempclose_clientlist[i].timestamp != 0)
1090 DHT_bootstrap(tempclose_clientlist[i].ip_port, tempclose_clientlist[i].client_id); 1335 DHT_bootstrap( tempclose_clientlist[i].ip_port,
1336 tempclose_clientlist[i].client_id );
1337 }
1091 return 0; 1338 return 0;
1092} 1339}
1093 1340
1094/* returns 0 if we are not connected to the DHT 1341/* returns 0 if we are not connected to the DHT
1095 returns 1 if we are */ 1342 * returns 1 if we are
1343 */
1096int DHT_isconnected() 1344int DHT_isconnected()
1097{ 1345{
1098 uint32_t i; 1346 uint32_t i;
1099 uint32_t temp_time = unix_time(); 1347 uint64_t temp_time = unix_time();
1100 for(i = 0; i < LCLIENT_LIST; ++i) 1348
1101 if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) 1349 for(i = 0; i < LCLIENT_LIST; ++i) {
1350 if(!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT))
1102 return 1; 1351 return 1;
1352 }
1103 return 0; 1353 return 0;
1104} 1354}
diff --git a/core/DHT.h b/core/DHT.h
index dbb640a5..ffa02087 100644
--- a/core/DHT.h
+++ b/core/DHT.h
@@ -31,7 +31,7 @@ extern "C" {
31#endif 31#endif
32 32
33/* Current time, unix format */ 33/* Current time, unix format */
34#define unix_time() ((uint32_t)time(NULL)) 34#define unix_time() ((uint64_t)time(NULL))
35 35
36/* size of the client_id in bytes */ 36/* size of the client_id in bytes */
37#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES 37#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES
diff --git a/core/LAN_discovery.c b/core/LAN_discovery.c
index 0a23914d..72e00d32 100644
--- a/core/LAN_discovery.c
+++ b/core/LAN_discovery.c
@@ -23,13 +23,70 @@
23 23
24#include "LAN_discovery.h" 24#include "LAN_discovery.h"
25 25
26#define MAX_INTERFACES 16
26 27
27/*Return the broadcast ip 28#ifdef __linux
28 TODO: make it return the real one, not the 255.255.255.255 one.*/ 29/* get the first working broadcast address that's not from "lo"
30 * returns higher than 0 on success
31 * returns 0 on error */
32uint32_t get_broadcast(void)
33{
34 /* not sure how many platforms this will
35 * run on, so it's wrapped in __linux for now */
36 struct sockaddr_in *sock_holder = NULL;
37 struct ifreq i_faces[MAX_INTERFACES];
38 struct ifconf ifconf;
39 int count = 0;
40 int sock = 0;
41 int i = 0;
42
43 /* configure ifconf for the ioctl call */
44 if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
45 perror("[!] get_broadcast: socket() error");
46 return 0;
47 }
48
49 memset(i_faces, 0, sizeof(struct ifreq) * MAX_INTERFACES);
50
51 ifconf.ifc_buf = (char *)i_faces;
52 ifconf.ifc_len = sizeof(i_faces);
53 count = ifconf.ifc_len / sizeof(struct ifreq);
54 if(ioctl(sock, SIOCGIFCONF, &ifconf) < 0) {
55 perror("get_broadcast: ioctl() error");
56 return 0;
57 }
58
59 for(i = 0; i < count; i++) {
60 /* skip the loopback interface, as it's useless */
61 if(strcmp(i_faces[i].ifr_name, "lo") != 0) {
62 if(ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) {
63 perror("[!] get_broadcast: ioctl error");
64 return 0;
65 }
66
67 /* just to clarify where we're getting the values from */
68 sock_holder = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
69 break;
70 }
71 }
72 close(sock);
73
74 return sock_holder->sin_addr.s_addr;
75}
76#endif
77
78/* Return the broadcast ip */
29IP broadcast_ip() 79IP broadcast_ip()
30{ 80{
31 IP ip; 81 IP ip;
82 #ifdef __linux
83 ip.i = get_broadcast();
84 if(ip.i == 0)
85 /* error errored, but try anyway? */
86 ip.i = ~0;
87 #else
32 ip.i = ~0; 88 ip.i = ~0;
89 #endif
33 return ip; 90 return ip;
34} 91}
35 92
diff --git a/core/LAN_discovery.h b/core/LAN_discovery.h
index 4ca65c03..96a6e6ad 100644
--- a/core/LAN_discovery.h
+++ b/core/LAN_discovery.h
@@ -28,6 +28,13 @@
28 28
29#include "DHT.h" 29#include "DHT.h"
30 30
31/* used for get_broadcast() */
32#ifdef __linux
33#include <sys/ioctl.h>
34#include <arpa/inet.h>
35#include <linux/netdevice.h>
36#endif
37
31#ifdef __cplusplus 38#ifdef __cplusplus
32extern "C" { 39extern "C" {
33#endif 40#endif
diff --git a/core/Lossless_UDP.c b/core/Lossless_UDP.c
index 6be8328f..33b8eb19 100644
--- a/core/Lossless_UDP.c
+++ b/core/Lossless_UDP.c
@@ -21,67 +21,95 @@
21 * 21 *
22 */ 22 */
23 23
24/* TODO: clean this file a bit. 24/*
25 There are a couple of useless variables to get rid of. */ 25 * TODO: clean this file a bit.
26 * There are a couple of useless variables to get rid of.
27 */
28
26#include "Lossless_UDP.h" 29#include "Lossless_UDP.h"
27 30
28/* maximum data packets in sent and receive queues. */ 31/* maximum data packets in sent and receive queues. */
29#define MAX_QUEUE_NUM 16 32#define MAX_QUEUE_NUM 16
30
31/* maximum length of the data in the data packets */
32/* #define MAX_DATA_SIZE 1024 */ /* defined in Lossless_UDP.h */
33 33
34/* maximum number of data packets in the buffer */ 34/* maximum number of data packets in the buffer */
35#define BUFFER_PACKET_NUM (16-1) 35#define BUFFER_PACKET_NUM (16-1)
36 36
37/* Lossless UDP connection timeout. 37/* timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT */
38timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT */
39#define CONNEXION_TIMEOUT 5 38#define CONNEXION_TIMEOUT 5
40 39
41/* initial amount of sync/hanshake packets to send per second. */ 40/* initial amount of sync/hanshake packets to send per second. */
42#define SYNC_RATE 2 41#define SYNC_RATE 2
43 42
44/* initial send rate of data. */ 43/* initial send rate of data. */
45#define DATA_SYNC_RATE 30 44#define DATA_SYNC_RATE 30
46 45
47typedef struct { 46typedef struct {
48 uint8_t data[MAX_DATA_SIZE]; 47 uint8_t data[MAX_DATA_SIZE];
49 uint16_t size; 48 uint16_t size;
50} Data; 49} Data;
51 50
52typedef struct { 51typedef struct {
53 IP_Port ip_port; 52 IP_Port ip_port;
54 uint8_t status; /* 0 if connection is dead, 1 if attempting handshake, 53
55 2 if handshake is done (we start sending SYNC packets) 54 /*
56 3 if we are sending SYNC packets and can send data 55 * 0 if connection is dead, 1 if attempting handshake,
57 4 if the connection has timed out. */ 56 * 2 if handshake is done (we start sending SYNC packets)
58 57 * 3 if we are sending SYNC packets and can send data
59 uint8_t inbound; /* 1 or 2 if connection was initiated by someone else, 0 if not. 58 * 4 if the connection has timed out.
60 2 if incoming_connection() has not returned it yet, 1 if it has. */ 59 */
61 60 uint8_t status;
62 uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */ 61
63 uint16_t data_rate; /* current data packet send rate packets per second. */ 62 /*
64 uint64_t last_SYNC; /* time at which our last SYNC packet was sent. */ 63 * 1 or 2 if connection was initiated by someone else, 0 if not.
65 uint64_t last_sent; /* time at which our last data or handshake packet was sent. */ 64 * 2 if incoming_connection() has not returned it yet, 1 if it has.
66 uint64_t last_recvSYNC; /* time at which we last received a SYNC packet from the other */ 65 */
67 uint64_t last_recvdata; /* time at which we last received a DATA packet from the other */ 66 uint8_t inbound;
68 uint64_t killat; /* time at which to kill the connection */ 67
69 Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */ 68 uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */
70 Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */ 69 uint16_t data_rate; /* current data packet send rate packets per second. */
71 uint32_t handshake_id1; 70
72 uint32_t handshake_id2; 71 uint64_t last_SYNC; /* time our last SYNC packet was sent. */
73 uint32_t recv_packetnum; /* number of data packets received (also used as handshake_id1) */ 72 uint64_t last_sent; /* time our last data or handshake packet was sent. */
74 uint32_t orecv_packetnum; /* number of packets received by the other peer */ 73 uint64_t last_recvSYNC; /* time we last received a SYNC packet from the other */
75 uint32_t sent_packetnum; /* number of data packets sent */ 74 uint64_t last_recvdata; /* time we last received a DATA packet from the other */
76 uint32_t osent_packetnum; /* number of packets sent by the other peer. */ 75 uint64_t killat; /* time to kill the connection */
77 uint32_t sendbuff_packetnum; /* number of latest packet written onto the sendbuffer */ 76
78 uint32_t successful_sent; /* we know all packets before that number were successfully sent */ 77 Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */
79 uint32_t successful_read; /* packet number of last packet read with the read_packet function */ 78 Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */
80 uint32_t req_packets[BUFFER_PACKET_NUM]; /* list of currently requested packet numbers(by the other person) */ 79
81 uint16_t num_req_paquets; /* total number of currently requested packets(by the other person) */ 80 uint32_t handshake_id1;
82 uint8_t recv_counter; 81 uint32_t handshake_id2;
83 uint8_t send_counter; 82
84 uint8_t timeout; /* connection timeout in seconds. */ 83 /* number of data packets received (also used as handshake_id1) */
84 uint32_t recv_packetnum;
85
86 /* number of packets received by the other peer */
87 uint32_t orecv_packetnum;
88
89 /* number of data packets sent */
90 uint32_t sent_packetnum;
91
92 /* number of packets sent by the other peer. */
93 uint32_t osent_packetnum;
94
95 /* number of latest packet written onto the sendbuffer */
96 uint32_t sendbuff_packetnum;
97
98 /* we know all packets before that number were successfully sent */
99 uint32_t successful_sent;
100
101 /* packet number of last packet read with the read_packet function */
102 uint32_t successful_read;
103
104 /* list of currently requested packet numbers(by the other person) */
105 uint32_t req_packets[BUFFER_PACKET_NUM];
106
107 /* total number of currently requested packets(by the other person) */
108 uint16_t num_req_paquets;
109
110 uint8_t recv_counter;
111 uint8_t send_counter;
112 uint8_t timeout; /* connection timeout in seconds. */
85} Connection; 113} Connection;
86 114
87 115
@@ -94,26 +122,33 @@ static uint32_t connections_number; /* Number of connections in connections arra
94 122
95/* Functions */ 123/* Functions */
96 124
97/* get connection id from IP_Port 125/*
98 return -1 if there are no connections like we are looking for 126 * Get connection id from IP_Port
99 return id if it found it */ 127 * Return -1 if there are no connections like we are looking for
128 * Return id if it found it
129 */
100int getconnection_id(IP_Port ip_port) 130int getconnection_id(IP_Port ip_port)
101{ 131{
102 uint32_t i; 132 uint32_t i;
103 for (i = 0; i < MAX_CONNECTIONS; ++i) { 133 for (i = 0; i < MAX_CONNECTIONS; ++i) {
104 if (connections[i].ip_port.ip.i == ip_port.ip.i && 134 if (connections[i].ip_port.ip.i == ip_port.ip.i &&
105 connections[i].ip_port.port == ip_port.port && connections[i].status > 0) 135 connections[i].ip_port.port == ip_port.port &&
136 connections[i].status > 0)
106 return i; 137 return i;
107 } 138 }
139
108 return -1; 140 return -1;
109} 141}
110 142
111/* table of random numbers used below. */ 143/* table of random numbers used below. */
112static uint32_t randtable[6][256]; 144static uint32_t randtable[6][256];
113 145
114/* generate a handshake_id which depends on the ip_port. 146/*
115 this function will always give one unique handshake_id per ip_port. 147 * Generate a handshake_id which depends on the ip_port.
116 TODO: make this better */ 148 * This function will always give one unique handshake_id per ip_port.
149 *
150 * TODO: make this better
151 */
117uint32_t handshake_id(IP_Port source) 152uint32_t handshake_id(IP_Port source)
118{ 153{
119 uint32_t id = 0, i; 154 uint32_t id = 0, i;
@@ -124,21 +159,27 @@ uint32_t handshake_id(IP_Port source)
124 } 159 }
125 if (id == 0) /* id can't be zero */ 160 if (id == 0) /* id can't be zero */
126 id = 1; 161 id = 1;
162
127 return id; 163 return id;
128} 164}
129 165
130/* change the hnshake id associated with that ip_port 166/*
131 TODO: make this better */ 167 * Change the hanshake id associated with that ip_port
168 *
169 * TODO: make this better
170 */
132void change_handshake(IP_Port source) 171void change_handshake(IP_Port source)
133{ 172{
134 uint8_t rand = random_int() % 4; 173 uint8_t rand = random_int() % 4;
135 randtable[rand][((uint8_t *)&source)[rand]] = random_int(); 174 randtable[rand][((uint8_t *)&source)[rand]] = random_int();
136} 175}
137 176
138/* initialize a new connection to ip_port 177/*
139 returns an integer corresponding to the connection id. 178 * Initialize a new connection to ip_port
140 return -1 if it could not initialize the connection. 179 * Returns an integer corresponding to the connection idt
141 if there already was an existing connection to that ip_port return its number. */ 180 * Return -1 if it could not initialize the connectiont
181 * If there already was an existing connection to that ip_port return its number.
182 */
142int new_connection(IP_Port ip_port) 183int new_connection(IP_Port ip_port)
143{ 184{
144 int connect = getconnection_id(ip_port); 185 int connect = getconnection_id(ip_port);
@@ -148,8 +189,10 @@ int new_connection(IP_Port ip_port)
148 if(connections_number == connections_length) { 189 if(connections_number == connections_length) {
149 Connection * temp; 190 Connection * temp;
150 temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); 191 temp = realloc(connections, sizeof(Connection) * (connections_length + 1));
192
151 if(temp == NULL) 193 if(temp == NULL)
152 return -1; 194 return -1;
195
153 memset(&temp[connections_length], 0, sizeof(Connection)); 196 memset(&temp[connections_length], 0, sizeof(Connection));
154 ++connections_length; 197 ++connections_length;
155 connections = temp; 198 connections = temp;
@@ -159,31 +202,38 @@ int new_connection(IP_Port ip_port)
159 for (i = 0; i < MAX_CONNECTIONS; ++i) { 202 for (i = 0; i < MAX_CONNECTIONS; ++i) {
160 if(connections[i].status == 0) { 203 if(connections[i].status == 0) {
161 memset(&connections[i], 0, sizeof(Connection)); 204 memset(&connections[i], 0, sizeof(Connection));
162 connections[i].ip_port = ip_port; 205 uint32_t handshake_id1 = handshake_id(ip_port);
163 connections[i].status = 1; 206
164 connections[i].inbound = 0; 207 connections[i] = (Connection) {
165 connections[i].handshake_id1 = handshake_id(ip_port); 208 .ip_port = ip_port,
166 connections[i].sent_packetnum = connections[i].handshake_id1; 209 .status = 1,
167 connections[i].sendbuff_packetnum = connections[i].handshake_id1; 210 .inbound = 0,
168 connections[i].successful_sent = connections[i].handshake_id1; 211 .handshake_id1 = handshake_id1,
169 connections[i].SYNC_rate = SYNC_RATE; 212 .sent_packetnum = handshake_id1,
170 connections[i].data_rate = DATA_SYNC_RATE; 213 .sendbuff_packetnum = handshake_id1,
171 connections[i].last_recvSYNC = current_time(); 214 .successful_sent = handshake_id1,
172 connections[i].last_sent = current_time(); 215 .SYNC_rate = SYNC_RATE,
173 connections[i].killat = ~0; 216 .data_rate = DATA_SYNC_RATE,
174 connections[i].send_counter = 0; 217 .last_recvSYNC = current_time(),
175 /* add randomness to timeout to prevent connections getting stuck in a loop. */ 218 .last_sent = current_time(),
176 connections[i].timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; 219 .killat = ~0,
220 .send_counter = 0,
221 /* add randomness to timeout to prevent connections getting stuck in a loop. */
222 .timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT
223 };
177 ++connections_number; 224 ++connections_number;
225
178 return i; 226 return i;
179 } 227 }
180 } 228 }
181 return -1; 229 return -1;
182} 230}
183 231
184/* initialize a new inbound connection from ip_port 232/*
185 returns an integer corresponding to the connection id. 233 * Initialize a new inbound connection from ip_port
186 return -1 if it could not initialize the connection. */ 234 * Returns an integer corresponding to the connection id.
235 * Return -1 if it could not initialize the connection.
236 */
187int new_inconnection(IP_Port ip_port) 237int new_inconnection(IP_Port ip_port)
188{ 238{
189 if (getconnection_id(ip_port) != -1) 239 if (getconnection_id(ip_port) != -1)
@@ -192,8 +242,10 @@ int new_inconnection(IP_Port ip_port)
192 if(connections_number == connections_length) { 242 if(connections_number == connections_length) {
193 Connection * temp; 243 Connection * temp;
194 temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); 244 temp = realloc(connections, sizeof(Connection) * (connections_length + 1));
245
195 if(temp == NULL) 246 if(temp == NULL)
196 return -1; 247 return -1;
248
197 memset(&temp[connections_length], 0, sizeof(Connection)); 249 memset(&temp[connections_length], 0, sizeof(Connection));
198 ++connections_length; 250 ++connections_length;
199 connections = temp; 251 connections = temp;
@@ -203,18 +255,24 @@ int new_inconnection(IP_Port ip_port)
203 for (i = 0; i < MAX_CONNECTIONS; ++i) { 255 for (i = 0; i < MAX_CONNECTIONS; ++i) {
204 if (connections[i].status == 0) { 256 if (connections[i].status == 0) {
205 memset(&connections[i], 0, sizeof(Connection)); 257 memset(&connections[i], 0, sizeof(Connection));
206 connections[i].ip_port = ip_port; 258 uint64_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT;
207 connections[i].status = 2; 259
208 connections[i].inbound = 2; 260 connections[i] = (Connection){
209 connections[i].SYNC_rate = SYNC_RATE; 261 .ip_port = ip_port,
210 connections[i].data_rate = DATA_SYNC_RATE; 262 .status = 2,
211 connections[i].last_recvSYNC = current_time(); 263 .inbound = 2,
212 connections[i].last_sent = current_time(); 264 .SYNC_rate = SYNC_RATE,
213 /* add randomness to timeout to prevent connections getting stuck in a loop. */ 265 .data_rate = DATA_SYNC_RATE,
214 connections[i].timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; 266 .last_recvSYNC = current_time(),
215 /* if this connection isn't handled within the timeout kill it. */ 267 .last_sent = current_time(),
216 connections[i].killat = current_time() + 1000000UL*connections[i].timeout; 268 .send_counter = 127,
217 connections[i].send_counter = 127; 269
270 /* add randomness to timeout to prevent connections getting stuck in a loop. */
271 .timeout = timeout,
272
273 /* if this connection isn't handled within the timeout kill it. */
274 .killat = current_time() + 1000000UL*timeout
275 };
218 ++connections_number; 276 ++connections_number;
219 return i; 277 return i;
220 } 278 }
@@ -222,8 +280,10 @@ int new_inconnection(IP_Port ip_port)
222 return -1; 280 return -1;
223} 281}
224 282
225/* returns an integer corresponding to the next connection in our incoming connection list 283/*
226 return -1 if there are no new incoming connections in the list. */ 284 * Returns an integer corresponding to the next connection in our incoming connection list.
285 * Return -1 if there are no new incoming connections in the list.
286 */
227int incoming_connection() 287int incoming_connection()
228{ 288{
229 uint32_t i; 289 uint32_t i;
@@ -233,9 +293,11 @@ int incoming_connection()
233 return i; 293 return i;
234 } 294 }
235 } 295 }
296
236 return -1; 297 return -1;
237} 298}
238/*Try to free some memory from the connections array.*/ 299
300/* Try to free some memory from the connections array. */
239static void free_connections() 301static void free_connections()
240{ 302{
241 uint32_t i; 303 uint32_t i;
@@ -245,16 +307,20 @@ static void free_connections()
245 307
246 if(connections_length == i) 308 if(connections_length == i)
247 return; 309 return;
310
248 Connection * temp; 311 Connection * temp;
249 temp = realloc(connections, sizeof(Connection) * i); 312 temp = realloc(connections, sizeof(Connection) * i);
250 if(temp == NULL && i != 0) 313 if(temp == NULL && i != 0)
251 return; 314 return;
315
252 connections = temp; 316 connections = temp;
253 connections_length = i; 317 connections_length = i;
254} 318}
255 319
256/* return -1 if it could not kill the connection. 320/*
257 return 0 if killed successfully */ 321 * Return -1 if it could not kill the connection.
322 * Return 0 if killed successfully
323 */
258int kill_connection(int connection_id) 324int kill_connection(int connection_id)
259{ 325{
260 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) { 326 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) {
@@ -269,9 +335,11 @@ int kill_connection(int connection_id)
269 return -1; 335 return -1;
270} 336}
271 337
272/* kill connection in seconds seconds. 338/*
273 return -1 if it can not kill the connection. 339 * Kill connection in seconds.
274 return 0 if it will kill it */ 340 * Return -1 if it can not kill the connection.
341 * Return 0 if it will kill it.
342 */
275int kill_connection_in(int connection_id, uint32_t seconds) 343int kill_connection_in(int connection_id, uint32_t seconds)
276{ 344{
277 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) { 345 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) {
@@ -283,12 +351,14 @@ int kill_connection_in(int connection_id, uint32_t seconds)
283 return -1; 351 return -1;
284} 352}
285 353
286/* check if connection is connected 354/*
287 return 0 no. 355 * Check if connection is connected:
288 return 1 if attempting handshake 356 * Return 0 no.
289 return 2 if handshake is done 357 * Return 1 if attempting handshake.
290 return 3 if fully connected 358 * Return 2 if handshake is done.
291 return 4 if timed out and waiting to be killed */ 359 * Return 3 if fully connected.
360 * Return 4 if timed out and waiting to be killed.
361 */
292int is_connected(int connection_id) 362int is_connected(int connection_id)
293{ 363{
294 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) 364 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS)
@@ -327,8 +397,10 @@ char id_packet(int connection_id)
327{ 397{
328 if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) 398 if (connection_id < 0 || connection_id >= MAX_CONNECTIONS)
329 return -1; 399 return -1;
400
330 if (recvqueue(connection_id) != 0 && connections[connection_id].status != 0) 401 if (recvqueue(connection_id) != 0 && connections[connection_id].status != 0)
331 return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0]; 402 return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0];
403
332 return -1; 404 return -1;
333} 405}
334 406
@@ -338,7 +410,7 @@ int read_packet(int connection_id, uint8_t * data)
338{ 410{
339 if (recvqueue(connection_id) != 0) { 411 if (recvqueue(connection_id) != 0) {
340 uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM; 412 uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM;
341 uint16_t size = connections[connection_id].recvbuffer[index].size; 413 uint16_t size = connections[connection_id].recvbuffer[index].size;
342 memcpy(data, connections[connection_id].recvbuffer[index].data, size); 414 memcpy(data, connections[connection_id].recvbuffer[index].data, size);
343 ++connections[connection_id].successful_read; 415 ++connections[connection_id].successful_read;
344 connections[connection_id].recvbuffer[index].size = 0; 416 connections[connection_id].recvbuffer[index].size = 0;
@@ -347,14 +419,15 @@ int read_packet(int connection_id, uint8_t * data)
347 return 0; 419 return 0;
348} 420}
349 421
350/* return 0 if data could not be put in packet queue 422/*
351 return 1 if data was put into the queue */ 423 * Return 0 if data could not be put in packet queue
424 * Return 1 if data was put into the queue
425 */
352int write_packet(int connection_id, uint8_t * data, uint32_t length) 426int write_packet(int connection_id, uint8_t * data, uint32_t length)
353{ 427{
354 if (length > MAX_DATA_SIZE) 428 if (length > MAX_DATA_SIZE || length == 0)
355 return 0;
356 if (length == 0)
357 return 0; 429 return 0;
430
358 if (sendqueue(connection_id) < BUFFER_PACKET_NUM) { 431 if (sendqueue(connection_id) < BUFFER_PACKET_NUM) {
359 uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM; 432 uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM;
360 memcpy(connections[connection_id].sendbuffer[index].data, data, length); 433 memcpy(connections[connection_id].sendbuffer[index].data, data, length);
@@ -362,6 +435,7 @@ int write_packet(int connection_id, uint8_t * data, uint32_t length)
362 connections[connection_id].sendbuff_packetnum++; 435 connections[connection_id].sendbuff_packetnum++;
363 return 1; 436 return 1;
364 } 437 }
438
365 return 0; 439 return 0;
366} 440}
367 441
@@ -371,8 +445,11 @@ uint32_t missing_packets(int connection_id, uint32_t * requested)
371 uint32_t number = 0; 445 uint32_t number = 0;
372 uint32_t i; 446 uint32_t i;
373 uint32_t temp; 447 uint32_t temp;
374 if (recvqueue(connection_id) >= (BUFFER_PACKET_NUM - 1)) /* don't request packets if the buffer is full. */ 448
449 /* don't request packets if the buffer is full. */
450 if (recvqueue(connection_id) >= (BUFFER_PACKET_NUM - 1))
375 return 0; 451 return 0;
452
376 for (i = connections[connection_id].recv_packetnum; i != connections[connection_id].osent_packetnum; i++) { 453 for (i = connections[connection_id].recv_packetnum; i != connections[connection_id].osent_packetnum; i++) {
377 if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) { 454 if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) {
378 temp = htonl(i); 455 temp = htonl(i);
@@ -380,14 +457,19 @@ uint32_t missing_packets(int connection_id, uint32_t * requested)
380 ++number; 457 ++number;
381 } 458 }
382 } 459 }
460
383 if(number == 0) 461 if(number == 0)
384 connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum; 462 connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum;
463
385 return number; 464 return number;
386} 465}
387 466
388/* Packet sending functions 467/*
389 One per packet type. 468 * BEGIN Packet sending functions
390 see docs/Lossless_UDP.txt for more information. */ 469 * One per packet type.
470 * see docs/Lossless_UDP.txt for more information.
471 */
472
391int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) 473int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2)
392{ 474{
393 uint8_t packet[1 + 4 + 4]; 475 uint8_t packet[1 + 4 + 4];
@@ -398,21 +480,22 @@ int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_i
398 memcpy(packet + 1, &temp, 4); 480 memcpy(packet + 1, &temp, 4);
399 temp = htonl(handshake_id2); 481 temp = htonl(handshake_id2);
400 memcpy(packet + 5, &temp, 4); 482 memcpy(packet + 5, &temp, 4);
483
401 return sendpacket(ip_port, packet, sizeof(packet)); 484 return sendpacket(ip_port, packet, sizeof(packet));
402} 485}
403 486
404int send_SYNC(uint32_t connection_id) 487int send_SYNC(uint32_t connection_id)
405{ 488{
406
407 uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)]; 489 uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)];
408 uint16_t index = 0; 490 uint16_t index = 0;
409 491
410 IP_Port ip_port = connections[connection_id].ip_port; 492 IP_Port ip_port = connections[connection_id].ip_port;
411 uint8_t counter = connections[connection_id].send_counter; 493 uint8_t counter = connections[connection_id].send_counter;
412 uint32_t recv_packetnum = htonl(connections[connection_id].recv_packetnum); 494 uint32_t recv_packetnum = htonl(connections[connection_id].recv_packetnum);
413 uint32_t sent_packetnum = htonl(connections[connection_id].sent_packetnum); 495 uint32_t sent_packetnum = htonl(connections[connection_id].sent_packetnum);
496
414 uint32_t requested[BUFFER_PACKET_NUM]; 497 uint32_t requested[BUFFER_PACKET_NUM];
415 uint32_t number = missing_packets(connection_id, requested); 498 uint32_t number = missing_packets(connection_id, requested);
416 499
417 packet[0] = 17; 500 packet[0] = 17;
418 index += 1; 501 index += 1;
@@ -462,17 +545,24 @@ int send_DATA(uint32_t connection_id)
462 return 0; 545 return 0;
463} 546}
464 547
465/* END of packet sending functions */ 548/*
549 * END of packet sending functions
550 *
551 *
552 * BEGIN Packet handling functions
553 * One to handle each type of packets we receive
554 */
555
466 556
467/* Packet handling functions 557/* Return 0 if handled correctly, 1 if packet is bad. */
468 One to handle each type of packets we receive
469 return 0 if handled correctly, 1 if packet is bad. */
470int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source) 558int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
471{ 559{
472 if (length != (1 + 4 + 4)) 560 if (length != (1 + 4 + 4))
473 return 1; 561 return 1;
562
474 uint32_t temp; 563 uint32_t temp;
475 uint32_t handshake_id1, handshake_id2; 564 uint32_t handshake_id1, handshake_id2;
565
476 int connection = getconnection_id(source); 566 int connection = getconnection_id(source);
477 memcpy(&temp, packet + 1, 4); 567 memcpy(&temp, packet + 1, 4);
478 handshake_id1 = ntohl(temp); 568 handshake_id1 = ntohl(temp);
@@ -485,21 +575,22 @@ int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
485 } 575 }
486 if (is_connected(connection) != 1) 576 if (is_connected(connection) != 1)
487 return 1; 577 return 1;
488 if (handshake_id2 == connections[connection].handshake_id1) { /* if handshake_id2 is what we sent previously as handshake_id1 */ 578
579 /* if handshake_id2 is what we sent previously as handshake_id1 */
580 if (handshake_id2 == connections[connection].handshake_id1) {
489 connections[connection].status = 2; 581 connections[connection].status = 2;
490 /* NOTE: is this necessary? 582 /* NOTE: is this necessary?
491 connections[connection].handshake_id2 = handshake_id1; */ 583 connections[connection].handshake_id2 = handshake_id1; */
492 connections[connection].orecv_packetnum = handshake_id2; 584 connections[connection].orecv_packetnum = handshake_id2;
493 connections[connection].osent_packetnum = handshake_id1; 585 connections[connection].osent_packetnum = handshake_id1;
494 connections[connection].recv_packetnum = handshake_id1; 586 connections[connection].recv_packetnum = handshake_id1;
495 connections[connection].successful_read = handshake_id1; 587 connections[connection].successful_read = handshake_id1;
496 } 588 }
497 return 0;
498 589
590 return 0;
499} 591}
500 592
501/* returns 1 if sync packet is valid 593/* returns 1 if sync packet is valid 0 if not. */
502 0 if not. */
503int SYNC_valid(uint32_t length) 594int SYNC_valid(uint32_t length)
504{ 595{
505 if (length < 4 + 4 + 2) 596 if (length < 4 + 4 + 2)
@@ -510,19 +601,19 @@ int SYNC_valid(uint32_t length)
510 return 1; 601 return 1;
511} 602}
512 603
513/* case 1: */ 604/* case 1 in handle_SYNC: */
514int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) 605int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum)
515{ 606{
516 if (handshake_id(source) == recv_packetnum) { 607 if (handshake_id(source) == recv_packetnum) {
517 int x = new_inconnection(source); 608 int x = new_inconnection(source);
518 if (x != -1) { 609 if (x != -1) {
519 connections[x].orecv_packetnum = recv_packetnum; 610 connections[x].orecv_packetnum = recv_packetnum;
520 connections[x].sent_packetnum = recv_packetnum; 611 connections[x].sent_packetnum = recv_packetnum;
521 connections[x].sendbuff_packetnum = recv_packetnum; 612 connections[x].sendbuff_packetnum = recv_packetnum;
522 connections[x].successful_sent = recv_packetnum; 613 connections[x].successful_sent = recv_packetnum;
523 connections[x].osent_packetnum = sent_packetnum; 614 connections[x].osent_packetnum = sent_packetnum;
524 connections[x].recv_packetnum = sent_packetnum; 615 connections[x].recv_packetnum = sent_packetnum;
525 connections[x].successful_read = sent_packetnum; 616 connections[x].successful_read = sent_packetnum;
526 617
527 return x; 618 return x;
528 } 619 }
@@ -530,7 +621,7 @@ int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnu
530 return -1; 621 return -1;
531} 622}
532 623
533/* case 2: */ 624/* case 2 in handle_SYNC: */
534int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) 625int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum)
535{ 626{
536 if (recv_packetnum == connections[connection_id].orecv_packetnum) { 627 if (recv_packetnum == connections[connection_id].orecv_packetnum) {
@@ -543,7 +634,7 @@ int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, ui
543 } 634 }
544 return 1; 635 return 1;
545} 636}
546/* case 3: */ 637/* case 3 in handle_SYNC: */
547int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum, uint32_t * req_packets, 638int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum, uint32_t * req_packets,
548 uint16_t number) 639 uint16_t number)
549{ 640{
@@ -553,17 +644,25 @@ int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, ui
553 uint32_t comp_2 = (sent_packetnum - connections[connection_id].successful_read); */ 644 uint32_t comp_2 = (sent_packetnum - connections[connection_id].successful_read); */
554 uint32_t comp_1 = (recv_packetnum - connections[connection_id].orecv_packetnum); 645 uint32_t comp_1 = (recv_packetnum - connections[connection_id].orecv_packetnum);
555 uint32_t comp_2 = (sent_packetnum - connections[connection_id].osent_packetnum); 646 uint32_t comp_2 = (sent_packetnum - connections[connection_id].osent_packetnum);
556 if (comp_1 <= BUFFER_PACKET_NUM && comp_2 <= BUFFER_PACKET_NUM && comp_counter < 10 && comp_counter != 0) { /* packet valid */ 647
648 /* packet valid */
649 if (comp_1 <= BUFFER_PACKET_NUM &&
650 comp_2 <= BUFFER_PACKET_NUM &&
651 comp_counter < 10 && comp_counter != 0) {
652
557 connections[connection_id].orecv_packetnum = recv_packetnum; 653 connections[connection_id].orecv_packetnum = recv_packetnum;
558 connections[connection_id].osent_packetnum = sent_packetnum; 654 connections[connection_id].osent_packetnum = sent_packetnum;
559 connections[connection_id].successful_sent = recv_packetnum; 655 connections[connection_id].successful_sent = recv_packetnum;
560 connections[connection_id].last_recvSYNC = current_time(); 656 connections[connection_id].last_recvSYNC = current_time();
561 connections[connection_id].recv_counter = counter; 657 connections[connection_id].recv_counter = counter;
658
562 ++connections[connection_id].send_counter; 659 ++connections[connection_id].send_counter;
660
563 for (i = 0; i < number; ++i) { 661 for (i = 0; i < number; ++i) {
564 temp = ntohl(req_packets[i]); 662 temp = ntohl(req_packets[i]);
565 memcpy(connections[connection_id].req_packets + i, &temp, 4 * number); 663 memcpy(connections[connection_id].req_packets + i, &temp, 4 * number);
566 } 664 }
665
567 connections[connection_id].num_req_paquets = number; 666 connections[connection_id].num_req_paquets = number;
568 return 0; 667 return 0;
569 } 668 }
@@ -575,6 +674,7 @@ int handle_SYNC(uint8_t *packet, uint32_t length, IP_Port source)
575 674
576 if (!SYNC_valid(length)) 675 if (!SYNC_valid(length))
577 return 1; 676 return 1;
677
578 int connection = getconnection_id(source); 678 int connection = getconnection_id(source);
579 uint8_t counter; 679 uint8_t counter;
580 uint32_t temp; 680 uint32_t temp;
@@ -587,19 +687,27 @@ int handle_SYNC(uint8_t *packet, uint32_t length, IP_Port source)
587 recv_packetnum = ntohl(temp); 687 recv_packetnum = ntohl(temp);
588 memcpy(&temp,packet + 6, 4); 688 memcpy(&temp,packet + 6, 4);
589 sent_packetnum = ntohl(temp); 689 sent_packetnum = ntohl(temp);
690
590 if (number != 0) 691 if (number != 0)
591 memcpy(req_packets, packet + 10, 4 * number); 692 memcpy(req_packets, packet + 10, 4 * number);
693
592 if (connection == -1) 694 if (connection == -1)
593 return handle_SYNC1(source, recv_packetnum, sent_packetnum); 695 return handle_SYNC1(source, recv_packetnum, sent_packetnum);
696
594 if (connections[connection].status == 2) 697 if (connections[connection].status == 2)
595 return handle_SYNC2(connection, counter, recv_packetnum, sent_packetnum); 698 return handle_SYNC2(connection, counter,
699 recv_packetnum, sent_packetnum);
700
596 if (connections[connection].status == 3) 701 if (connections[connection].status == 3)
597 return handle_SYNC3(connection, counter, recv_packetnum, sent_packetnum, req_packets, number); 702 return handle_SYNC3(connection, counter, recv_packetnum,
703 sent_packetnum, req_packets, number);
598 return 0; 704 return 0;
599} 705}
600 706
601/* add a packet to the received buffer and set the recv_packetnum of the connection to its proper value. 707/*
602 return 1 if data was too big, 0 if not. */ 708 * Add a packet to the received buffer and set the recv_packetnum of the
709 * connection to its proper value. Return 1 if data was too big, 0 if not.
710 */
603int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) 711int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
604{ 712{
605 if (size > MAX_DATA_SIZE) 713 if (size > MAX_DATA_SIZE)
@@ -608,16 +716,22 @@ int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
608 uint32_t i; 716 uint32_t i;
609 uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM; 717 uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM;
610 uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum; 718 uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum;
719
611 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { 720 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) {
612 if (i == data_num) { 721 if (i == data_num) {
613 memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size); 722 memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size);
723
614 connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size; 724 connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size;
615 connections[connection_id].last_recvdata = current_time(); 725 connections[connection_id].last_recvdata = current_time();
616 if (sent_packet < BUFFER_PACKET_NUM) 726
727 if (sent_packet < BUFFER_PACKET_NUM) {
617 connections[connection_id].osent_packetnum = data_num; 728 connections[connection_id].osent_packetnum = data_num;
729 }
730
618 break; 731 break;
619 } 732 }
620 } 733 }
734
621 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { 735 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) {
622 if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0) 736 if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0)
623 connections[connection_id].recv_packetnum = i; 737 connections[connection_id].recv_packetnum = i;
@@ -635,25 +749,30 @@ int handle_data(uint8_t *packet, uint32_t length, IP_Port source)
635 if (connection == -1) 749 if (connection == -1)
636 return 1; 750 return 1;
637 751
638 if (connections[connection].status != 3) /* Drop the data packet if connection is not connected. */ 752 /* Drop the data packet if connection is not connected. */
753 if (connections[connection].status != 3)
639 return 1; 754 return 1;
640 755
641 if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) 756 if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1)
642 return 1; 757 return 1;
758
643 uint32_t temp; 759 uint32_t temp;
644 uint32_t number; 760 uint32_t number;
645 uint16_t size = length - 1 - 4; 761 uint16_t size = length - 1 - 4;
646 762
647 memcpy(&temp, packet + 1, 4); 763 memcpy(&temp, packet + 1, 4);
648 number = ntohl(temp); 764 number = ntohl(temp);
765
649 return add_recv(connection, number, packet + 5, size); 766 return add_recv(connection, number, packet + 5, size);
650} 767}
651 768
652/* END of packet handling functions */ 769/*
770 * END of packet handling functions
771 */
653 772
654int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source) 773int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source)
655{ 774{
656 switch (packet[0]) { //TODO: check if no break statement is correct??? 775 switch (packet[0]) {
657 case 16: 776 case 16:
658 return handle_handshake(packet, length, source); 777 return handle_handshake(packet, length, source);
659 778
@@ -670,8 +789,10 @@ int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source)
670 return 0; 789 return 0;
671} 790}
672 791
673/* Send handshake requests 792/*
674 handshake packets are sent at the same rate as SYNC packets */ 793 * Send handshake requests
794 * handshake packets are sent at the same rate as SYNC packets
795 */
675void doNew() 796void doNew()
676{ 797{
677 uint32_t i; 798 uint32_t i;
@@ -684,10 +805,13 @@ void doNew()
684 } 805 }
685 806
686 /* kill all timed out connections */ 807 /* kill all timed out connections */
687 if ( connections[i].status > 0 && (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time && 808 if (connections[i].status > 0 &&
688 connections[i].status != 4) 809 (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time &&
689 /* kill_connection(i); */ 810 connections[i].status != 4) {
690 connections[i].status = 4; 811 connections[i].status = 4;
812 /* kill_connection(i); */
813 }
814
691 if (connections[i].status > 0 && connections[i].killat < temp_time) 815 if (connections[i].status > 0 && connections[i].killat < temp_time)
692 kill_connection(i); 816 kill_connection(i);
693 } 817 }
@@ -720,11 +844,13 @@ void doData()
720 } 844 }
721} 845}
722 846
723/* TODO: flow control.
724 automatically adjusts send rates of packets for optimal transmission. */
725
726#define MAX_SYNC_RATE 10 847#define MAX_SYNC_RATE 10
727 848
849/*
850 * Automatically adjusts send rates of packets for optimal transmission.
851 *
852 * TODO: flow control.
853 */
728void adjustRates() 854void adjustRates()
729{ 855{
730 uint32_t i; 856 uint32_t i;
@@ -744,8 +870,7 @@ void adjustRates()
744 } 870 }
745} 871}
746 872
747/* Call this function a couple times per second 873/* Call this function a couple times per second It's the main loop. */
748 It's the main loop. */
749void doLossless_UDP() 874void doLossless_UDP()
750{ 875{
751 doNew(); 876 doNew();
diff --git a/core/Lossless_UDP.h b/core/Lossless_UDP.h
index 033bc480..573e1ab9 100644
--- a/core/Lossless_UDP.h
+++ b/core/Lossless_UDP.h
@@ -33,70 +33,90 @@ extern "C" {
33/* maximum length of the data in the data packets */ 33/* maximum length of the data in the data packets */
34#define MAX_DATA_SIZE 1024 34#define MAX_DATA_SIZE 1024
35 35
36/* Functions */ 36/*
37 37 * Initialize a new connection to ip_port
38/* initialize a new connection to ip_port 38 * Returns an integer corresponding to the connection id.
39 returns an integer corresponding to the connection id. 39 * Return -1 if it could not initialize the connection.
40 return -1 if it could not initialize the connection. 40 * Return number if there already was an existing connection to that ip_port.
41 if there already was an existing connection to that ip_port return its number. */ 41 */
42int new_connection(IP_Port ip_port); 42int new_connection(IP_Port ip_port);
43 43
44/* get connection id from IP_Port 44/*
45 return -1 if there are no connections like we are looking for 45 * Get connection id from IP_Port.
46 return id if it found it */ 46 * Return -1 if there are no connections like we are looking for.
47 * Return id if it found it .
48 */
47int getconnection_id(IP_Port ip_port); 49int getconnection_id(IP_Port ip_port);
48 50
49/* returns an integer corresponding to the next connection in our imcoming connection list 51/*
50 return -1 if there are no new incoming connections in the list. */ 52 * Returns an int corresponding to the next connection in our imcoming connection list
53 * Return -1 if there are no new incoming connections in the list.
54 */
51int incoming_connection(); 55int incoming_connection();
52 56
53/* return -1 if it could not kill the connection. 57/*
54 return 0 if killed successfully */ 58 * Return -1 if it could not kill the connection.
59 * Return 0 if killed successfully
60 */
55int kill_connection(int connection_id); 61int kill_connection(int connection_id);
56 62
57/* kill connection in seconds seconds. 63/*
58 return -1 if it can not kill the connection. 64 * Kill connection in seconds seconds.
59 return 0 if it will kill it */ 65 * Return -1 if it can not kill the connection.
66 * Return 0 if it will kill it
67 */
60int kill_connection_in(int connection_id, uint32_t seconds); 68int kill_connection_in(int connection_id, uint32_t seconds);
61 69
62/* returns the ip_port of the corresponding connection. 70/*
63 return 0 if there is no such connection. */ 71 * Returns the ip_port of the corresponding connection.
72 * Return 0 if there is no such connection.
73 */
64IP_Port connection_ip(int connection_id); 74IP_Port connection_ip(int connection_id);
65 75
66/* returns the id of the next packet in the queue 76/*
67 return -1 if no packet in queue */ 77 * Returns the id of the next packet in the queue
78 * Return -1 if no packet in queue
79 */
68char id_packet(int connection_id); 80char id_packet(int connection_id);
69 81
70/* return 0 if there is no received data in the buffer. 82/*
71 return length of received packet if successful */ 83 * Return 0 if there is no received data in the buffer.
84 * Return length of received packet if successful
85 */
72int read_packet(int connection_id, uint8_t *data); 86int read_packet(int connection_id, uint8_t *data);
73 87
74/* return 0 if data could not be put in packet queue 88/*
75 return 1 if data was put into the queue */ 89 * Return 0 if data could not be put in packet queue
90 * Return 1 if data was put into the queue
91 */
76int write_packet(int connection_id, uint8_t *data, uint32_t length); 92int write_packet(int connection_id, uint8_t *data, uint32_t length);
77 93
78/* returns the number of packets in the queue waiting to be successfully sent. */ 94/* Returns the number of packets in the queue waiting to be successfully sent. */
79uint32_t sendqueue(int connection_id); 95uint32_t sendqueue(int connection_id);
80 96
81/* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */ 97/*
98 * returns the number of packets in the queue waiting to be successfully
99 * read with read_packet(...)
100 */
82uint32_t recvqueue(int connection_id); 101uint32_t recvqueue(int connection_id);
83 102
84/* check if connection is connected 103/* Check if connection is connected:
85 return 0 no. 104 * Return 0 no.
86 return 1 if attempting handshake 105 * Return 1 if attempting handshake.
87 return 2 if handshake is done 106 * Return 2 if handshake is done.
88 return 3 if fully connected 107 * Return 3 if fully connected.
89 return 4 if timed out and wating to be killed */ 108 * Return 4 if timed out and wating to be killed.
109 */
90int is_connected(int connection_id); 110int is_connected(int connection_id);
91 111
92/* Call this function a couple times per second 112/* Call this function a couple times per second It's the main loop. */
93 It's the main loop. */
94void doLossless_UDP(); 113void doLossless_UDP();
95 114
96 115/*
97/* if we receive a Lossless_UDP packet we call this function so it can be handled. 116 * If we receive a Lossless_UDP packet, call this function so it can be handled.
98 return 0 if packet is handled correctly. 117 * Return 0 if packet is handled correctly.
99 return 1 if it didn't handle the packet or if the packet was shit. */ 118 * Return 1 if it didn't handle the packet or if the packet was shit.
119 */
100int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source); 120int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source);
101 121
102#ifdef __cplusplus 122#ifdef __cplusplus
diff --git a/core/Messenger.c b/core/Messenger.c
index eb59b81a..c768633e 100644
--- a/core/Messenger.c
+++ b/core/Messenger.c
@@ -27,7 +27,7 @@
27typedef struct { 27typedef struct {
28 uint8_t client_id[CLIENT_ID_SIZE]; 28 uint8_t client_id[CLIENT_ID_SIZE];
29 int crypt_connection_id; 29 int crypt_connection_id;
30 int friend_request_id; /* id of the friend request corresponding to the current friend request to the current friend. */ 30 uint64_t friend_request_id; /* id of the friend request corresponding to the current friend request to the current friend. */
31 uint8_t status; /* 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. */ 31 uint8_t status; /* 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. */
32 uint8_t info[MAX_DATA_SIZE]; /* the data that is sent during the friend requests we do */ 32 uint8_t info[MAX_DATA_SIZE]; /* the data that is sent during the friend requests we do */
33 uint8_t name[MAX_NAME_LENGTH]; 33 uint8_t name[MAX_NAME_LENGTH];
@@ -71,12 +71,6 @@ int getfriend_id(uint8_t *client_id)
71 return -1; 71 return -1;
72} 72}
73 73
74/* Returns number of friends */
75int getnumfriends()
76{
77 return numfriends;
78}
79
80/* copies the public key associated to that friend id into client_id buffer. 74/* copies the public key associated to that friend id into client_id buffer.
81 make sure that client_id is of size CLIENT_ID_SIZE. 75 make sure that client_id is of size CLIENT_ID_SIZE.
82 return 0 if success 76 return 0 if success
@@ -94,29 +88,36 @@ int getclient_id(int friend_id, uint8_t *client_id)
94 return -1; 88 return -1;
95} 89}
96 90
97/* add a friend 91/*
98 set the data that will be sent along with friend request 92 * add a friend
99 client_id is the client id of the friend 93 * set the data that will be sent along with friend request
100 data is the data and length is the length 94 * client_id is the client id of the friend
101 returns the friend number if success 95 * data is the data and length is the length
102 return -1 if key length is wrong. 96 * returns the friend number if success
103 return -2 if user's own key 97 * return FA_TOOLONG if message length is too long
104 return -3 if already a friend 98 * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte)
105 return -4 for other*/ 99 * return FAERR_OWNKEY if user's own key
100 * return FAERR_ALREADYSENT if friend request already sent or already a friend
101 * return FAERR_UNKNOWN for unknown error
102 */
106int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) 103int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
107{ 104{
108 if (length == 0 || length >= 105 if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES
109 (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) 106 - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES
110 return -1; 107 + crypto_box_ZEROBYTES))
108 return FAERR_TOOLONG;
109 if (length < 1)
110 return FAERR_NOMESSAGE;
111 if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) 111 if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0)
112 return -2; 112 return FAERR_OWNKEY;
113 if (getfriend_id(client_id) != -1) 113 if (getfriend_id(client_id) != -1)
114 return -3; 114 return FAERR_ALREADYSENT;
115
115 uint32_t i; 116 uint32_t i;
116 for (i = 0; i <= numfriends; ++i) { /*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/ 117 for (i = 0; i <= numfriends; ++i) { /*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/
117 if(friendlist[i].status == 0) { 118 if(friendlist[i].status == NOFRIEND) {
118 DHT_addfriend(client_id); 119 DHT_addfriend(client_id);
119 friendlist[i].status = 1; 120 friendlist[i].status = FRIEND_ADDED;
120 friendlist[i].crypt_connection_id = -1; 121 friendlist[i].crypt_connection_id = -1;
121 friendlist[i].friend_request_id = -1; 122 friendlist[i].friend_request_id = -1;
122 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); 123 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
@@ -129,7 +130,7 @@ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
129 return i; 130 return i;
130 } 131 }
131 } 132 }
132 return -4; 133 return FAERR_UNKNOWN;
133} 134}
134 135
135int m_addfriend_norequest(uint8_t * client_id) 136int m_addfriend_norequest(uint8_t * client_id)
@@ -138,9 +139,9 @@ int m_addfriend_norequest(uint8_t * client_id)
138 return -1; 139 return -1;
139 uint32_t i; 140 uint32_t i;
140 for (i = 0; i <= numfriends; ++i) {/*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/ 141 for (i = 0; i <= numfriends; ++i) {/*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/
141 if(friendlist[i].status == 0) { 142 if(friendlist[i].status == NOFRIEND) {
142 DHT_addfriend(client_id); 143 DHT_addfriend(client_id);
143 friendlist[i].status = 2; 144 friendlist[i].status = FRIEND_REQUESTED;
144 friendlist[i].crypt_connection_id = -1; 145 friendlist[i].crypt_connection_id = -1;
145 friendlist[i].friend_request_id = -1; 146 friendlist[i].friend_request_id = -1;
146 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); 147 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
@@ -168,7 +169,7 @@ int m_delfriend(int friendnumber)
168 uint32_t i; 169 uint32_t i;
169 170
170 for (i = numfriends; i != 0; --i) { 171 for (i = numfriends; i != 0; --i) {
171 if (friendlist[i-1].status != 0) 172 if (friendlist[i-1].status != NOFRIEND)
172 break; 173 break;
173 } 174 }
174 numfriends = i; 175 numfriends = i;
@@ -176,15 +177,15 @@ int m_delfriend(int friendnumber)
176 return 0; 177 return 0;
177} 178}
178 179
179/* return 4 if friend is online 180/* return FRIEND_ONLINE if friend is online
180 return 3 if friend is confirmed 181 return FRIEND_CONFIRMED if friend is confirmed
181 return 2 if the friend request was sent 182 return FRIEND_REQUESTED if the friend request was sent
182 return 1 if the friend was added 183 return FRIEND_ADDED if the friend was added
183 return 0 if there is no friend with that number */ 184 return NOFRIEND if there is no friend with that number */
184int m_friendstatus(int friendnumber) 185int m_friendstatus(int friendnumber)
185{ 186{
186 if (friendnumber < 0 || friendnumber >= numfriends) 187 if (friendnumber < 0 || friendnumber >= numfriends)
187 return 0; 188 return NOFRIEND;
188 return friendlist[friendnumber].status; 189 return friendlist[friendnumber].status;
189} 190}
190 191
@@ -195,7 +196,7 @@ int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length)
195{ 196{
196 if (friendnumber < 0 || friendnumber >= numfriends) 197 if (friendnumber < 0 || friendnumber >= numfriends)
197 return 0; 198 return 0;
198 if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != 4) 199 if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != FRIEND_ONLINE)
199 /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */ 200 /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */
200 return 0; 201 return 0;
201 uint8_t temp[MAX_DATA_SIZE]; 202 uint8_t temp[MAX_DATA_SIZE];
@@ -384,15 +385,15 @@ static void doFriends()
384 int len; 385 int len;
385 uint8_t temp[MAX_DATA_SIZE]; 386 uint8_t temp[MAX_DATA_SIZE];
386 for (i = 0; i < numfriends; ++i) { 387 for (i = 0; i < numfriends; ++i) {
387 if (friendlist[i].status == 1) { 388 if (friendlist[i].status == FRIEND_ADDED) {
388 int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); 389 int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
389 if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */ 390 if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */
390 friendlist[i].status = 2; 391 friendlist[i].status = FRIEND_REQUESTED;
391 else if (fr > 0) 392 else if (fr > 0)
392 friendlist[i].status = 2; 393 friendlist[i].status = FRIEND_REQUESTED;
393 } 394 }
394 if (friendlist[i].status == 2 || friendlist[i].status == 3) { /* friend is not online */ 395 if (friendlist[i].status == FRIEND_REQUESTED || friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */
395 if (friendlist[i].status == 2) { 396 if (friendlist[i].status == FRIEND_REQUESTED) {
396 if (friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/ 397 if (friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/
397 send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); 398 send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
398 friendlist[i].friend_request_id = unix_time(); 399 friendlist[i].friend_request_id = unix_time();
@@ -405,7 +406,7 @@ static void doFriends()
405 friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip); 406 friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip);
406 break; 407 break;
407 case 3: /* Connection is established */ 408 case 3: /* Connection is established */
408 friendlist[i].status = 4; 409 friendlist[i].status = FRIEND_ONLINE;
409 break; 410 break;
410 case 4: 411 case 4:
411 crypto_kill(friendlist[i].crypt_connection_id); 412 crypto_kill(friendlist[i].crypt_connection_id);
@@ -415,7 +416,7 @@ static void doFriends()
415 break; 416 break;
416 } 417 }
417 } 418 }
418 while (friendlist[i].status == 4) { /* friend is online */ 419 while (friendlist[i].status == FRIEND_ONLINE) { /* friend is online */
419 if (friendlist[i].name_sent == 0) { 420 if (friendlist[i].name_sent == 0) {
420 if (m_sendname(i, self_name, self_name_length)) 421 if (m_sendname(i, self_name, self_name_length))
421 friendlist[i].name_sent = 1; 422 friendlist[i].name_sent = 1;
@@ -455,7 +456,7 @@ static void doFriends()
455 if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */ 456 if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
456 crypto_kill(friendlist[i].crypt_connection_id); 457 crypto_kill(friendlist[i].crypt_connection_id);
457 friendlist[i].crypt_connection_id = -1; 458 friendlist[i].crypt_connection_id = -1;
458 friendlist[i].status = 3; 459 friendlist[i].status = FRIEND_CONFIRMED;
459 } 460 }
460 break; 461 break;
461 } 462 }
@@ -476,7 +477,7 @@ static void doInbound()
476 friendlist[friend_id].crypt_connection_id = 477 friendlist[friend_id].crypt_connection_id =
477 accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key); 478 accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key);
478 479
479 friendlist[friend_id].status = 3; 480 friendlist[friend_id].status = FRIEND_CONFIRMED;
480 } 481 }
481 } 482 }
482} 483}
@@ -484,7 +485,7 @@ static void doInbound()
484/*Interval in seconds between LAN discovery packet sending*/ 485/*Interval in seconds between LAN discovery packet sending*/
485#define LAN_DISCOVERY_INTERVAL 60 486#define LAN_DISCOVERY_INTERVAL 60
486 487
487static uint32_t last_LANdiscovery; 488static uint64_t last_LANdiscovery;
488 489
489/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/ 490/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/
490static void LANdiscovery() 491static void LANdiscovery()
diff --git a/core/Messenger.h b/core/Messenger.h
index 9ce96fb4..acf62a32 100644
--- a/core/Messenger.h
+++ b/core/Messenger.h
@@ -42,18 +42,36 @@ extern "C" {
42#define PACKET_ID_USERSTATUS 49 42#define PACKET_ID_USERSTATUS 49
43#define PACKET_ID_MESSAGE 64 43#define PACKET_ID_MESSAGE 64
44 44
45/* status definitions */
46#define FRIEND_ONLINE 4
47#define FRIEND_CONFIRMED 3
48#define FRIEND_REQUESTED 2
49#define FRIEND_ADDED 1
50#define NOFRIEND 0
51
52/* errors for m_addfriend
53 * FAERR - Friend Add Error */
54#define FAERR_TOOLONG -1
55#define FAERR_NOMESSAGE -2
56#define FAERR_OWNKEY -3
57#define FAERR_ALREADYSENT -4
58#define FAERR_UNKNOWN -5
59
45/* don't assume MAX_USERSTATUS_LENGTH will stay at 128, it may be increased 60/* don't assume MAX_USERSTATUS_LENGTH will stay at 128, it may be increased
46 to an absurdly large number later */ 61 to an absurdly large number later */
47 62
48/* add a friend 63/*
49 set the data that will be sent along with friend request 64 * add a friend
50 client_id is the client id of the friend 65 * set the data that will be sent along with friend request
51 data is the data and length is the length 66 * client_id is the client id of the friend
52 returns the friend number if success 67 * data is the data and length is the length
53 return -1 if key length is wrong. 68 * returns the friend number if success
54 return -2 if user's own key 69 * return -1 if message length is too long
55 return -3 if already a friend 70 * return -2 if no message (message length must be >= 1 byte)
56 return -4 for other*/ 71 * return -3 if user's own key
72 * return -4 if friend request already sent or already a friend
73 * return -5 for unknown error
74 */
57int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length); 75int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length);
58 76
59 77
diff --git a/core/net_crypto.c b/core/net_crypto.c
index a437c5ee..3b5b67f4 100644
--- a/core/net_crypto.c
+++ b/core/net_crypto.c
@@ -48,6 +48,12 @@ typedef struct {
48 48
49static Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS]; 49static Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS];
50 50
51#define CONN_NO_CONNECTION 0
52#define CONN_HANDSHAKE_SENT 1
53#define CONN_NOT_CONFIRMED 2
54#define CONN_ESTABLISHED 3
55#define CONN_TIMED_OUT 4
56
51#define MAX_INCOMING 64 57#define MAX_INCOMING 64
52 58
53/* keeps track of the connection numbers for friends request so we can check later if they were sent */ 59/* keeps track of the connection numbers for friends request so we can check later if they were sent */
@@ -60,23 +66,28 @@ static int incoming_connections[MAX_INCOMING];
60int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, 66int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
61 uint8_t *plain, uint32_t length, uint8_t *encrypted) 67 uint8_t *plain, uint32_t length, uint8_t *encrypted)
62{ 68{
63 if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE || length == 0) 69 if (length + crypto_box_MACBYTES > MAX_DATA_SIZE || length == 0)
64 return -1; 70 return -1;
65 71
66 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES] = {0}; 72 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0};
67 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES]; 73 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES];
68 uint8_t zeroes[crypto_box_BOXZEROBYTES] = {0};
69 74
70 memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */ 75 memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */
71 76
72 crypto_box(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, public_key, secret_key); 77 crypto_box(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, public_key, secret_key);
73 78
74 /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero */ 79 /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero
75 if (memcmp(temp_encrypted, zeroes, crypto_box_BOXZEROBYTES) != 0) 80 apparently memcmp should not be used so we do this instead:*/
81 uint32_t i;
82 uint32_t check = 0;
83 for(i = 0; i < crypto_box_BOXZEROBYTES; ++i) {
84 check |= temp_encrypted[i] ^ 0;
85 }
86 if(check != 0)
76 return -1; 87 return -1;
77 88
78 /* unpad the encrypted message */ 89 /* unpad the encrypted message */
79 memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); 90 memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES);
80 return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES; 91 return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES;
81} 92}
82 93
@@ -90,9 +101,8 @@ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
90 if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) 101 if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES)
91 return -1; 102 return -1;
92 103
93 uint8_t temp_plain[MAX_DATA_SIZE - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES]; 104 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES];
94 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0}; 105 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0};
95 uint8_t zeroes[crypto_box_ZEROBYTES] = {0};
96 106
97 memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */ 107 memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */
98 108
@@ -100,12 +110,18 @@ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
100 nonce, public_key, secret_key) == -1) 110 nonce, public_key, secret_key) == -1)
101 return -1; 111 return -1;
102 112
103 /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero */ 113 /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero
104 if (memcmp(temp_plain, zeroes, crypto_box_ZEROBYTES) != 0) 114 apparently memcmp should not be used so we do this instead:*/
115 uint32_t i;
116 uint32_t check = 0;
117 for(i = 0; i < crypto_box_ZEROBYTES; ++i) {
118 check |= temp_plain[i] ^ 0;
119 }
120 if(check != 0)
105 return -1; 121 return -1;
106 122
107 /* unpad the plain message */ 123 /* unpad the plain message */
108 memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES); 124 memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES);
109 return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; 125 return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES;
110} 126}
111 127
@@ -137,7 +153,7 @@ int read_cryptpacket(int crypt_connection_id, uint8_t *data)
137{ 153{
138 if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) 154 if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
139 return 0; 155 return 0;
140 if (crypto_connections[crypt_connection_id].status != 3) 156 if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED)
141 return 0; 157 return 0;
142 uint8_t temp_data[MAX_DATA_SIZE]; 158 uint8_t temp_data[MAX_DATA_SIZE];
143 int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data); 159 int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data);
@@ -163,7 +179,7 @@ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length)
163 return 0; 179 return 0;
164 if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) 180 if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1)
165 return 0; 181 return 0;
166 if (crypto_connections[crypt_connection_id].status != 3) 182 if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED)
167 return 0; 183 return 0;
168 uint8_t temp_data[MAX_DATA_SIZE]; 184 uint8_t temp_data[MAX_DATA_SIZE];
169 int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, 185 int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key,
@@ -283,7 +299,7 @@ int getcryptconnection_id(uint8_t *public_key)
283{ 299{
284 uint32_t i; 300 uint32_t i;
285 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 301 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
286 if (crypto_connections[i].status > 0) 302 if (crypto_connections[i].status != CONN_NO_CONNECTION)
287 if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) 303 if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0)
288 return i; 304 return i;
289 } 305 }
@@ -303,12 +319,12 @@ int crypto_connect(uint8_t *public_key, IP_Port ip_port)
303 return -1; 319 return -1;
304 } 320 }
305 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 321 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
306 if (crypto_connections[i].status == 0) { 322 if (crypto_connections[i].status == CONN_NO_CONNECTION) {
307 int id = new_connection(ip_port); 323 int id = new_connection(ip_port);
308 if (id == -1) 324 if (id == -1)
309 return -1; 325 return -1;
310 crypto_connections[i].number = id; 326 crypto_connections[i].number = id;
311 crypto_connections[i].status = 1; 327 crypto_connections[i].status = CONN_HANDSHAKE_SENT;
312 random_nonce(crypto_connections[i].recv_nonce); 328 random_nonce(crypto_connections[i].recv_nonce);
313 memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); 329 memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
314 crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key); 330 crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key);
@@ -362,9 +378,10 @@ int crypto_kill(int crypt_connection_id)
362{ 378{
363 if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) 379 if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
364 return 1; 380 return 1;
365 if (crypto_connections[crypt_connection_id].status != 0) { 381 if (crypto_connections[crypt_connection_id].status != CONN_NO_CONNECTION) {
366 crypto_connections[crypt_connection_id].status = 0; 382 crypto_connections[crypt_connection_id].status = CONN_NO_CONNECTION;
367 kill_connection(crypto_connections[crypt_connection_id].number); 383 kill_connection(crypto_connections[crypt_connection_id].number);
384 memset(&crypto_connections[crypt_connection_id], 0 ,sizeof(Crypto_Connection));
368 crypto_connections[crypt_connection_id].number = ~0; 385 crypto_connections[crypt_connection_id].number = ~0;
369 return 0; 386 return 0;
370 } 387 }
@@ -385,9 +402,9 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre
385 return -1; 402 return -1;
386 }*/ 403 }*/
387 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 404 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
388 if(crypto_connections[i].status == 0) { 405 if(crypto_connections[i].status == CONN_NO_CONNECTION) {
389 crypto_connections[i].number = connection_id; 406 crypto_connections[i].number = connection_id;
390 crypto_connections[i].status = 2; 407 crypto_connections[i].status = CONN_NOT_CONFIRMED;
391 random_nonce(crypto_connections[i].recv_nonce); 408 random_nonce(crypto_connections[i].recv_nonce);
392 memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); 409 memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
393 memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); 410 memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
@@ -400,9 +417,9 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre
400 crypto_connections[i].sessionpublic_key) == 1) { 417 crypto_connections[i].sessionpublic_key) == 1) {
401 increment_nonce(crypto_connections[i].recv_nonce); 418 increment_nonce(crypto_connections[i].recv_nonce);
402 uint32_t zero = 0; 419 uint32_t zero = 0;
403 crypto_connections[i].status = 3; /* connection status needs to be 3 for write_cryptpacket() to work */ 420 crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */
404 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); 421 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
405 crypto_connections[i].status = 2; /* set it to its proper value right after. */ 422 crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */
406 return i; 423 return i;
407 } 424 }
408 return -1; /* this should never happen. */ 425 return -1; /* this should never happen. */
@@ -418,7 +435,7 @@ int is_cryptoconnected(int crypt_connection_id)
418{ 435{
419 if (crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS) 436 if (crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS)
420 return crypto_connections[crypt_connection_id].status; 437 return crypto_connections[crypt_connection_id].status;
421 return 0; 438 return CONN_NO_CONNECTION;
422} 439}
423 440
424/* Generate our public and private keys 441/* Generate our public and private keys
@@ -477,7 +494,7 @@ static void receive_crypto()
477{ 494{
478 uint32_t i; 495 uint32_t i;
479 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 496 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
480 if (crypto_connections[i].status == 1) { 497 if (crypto_connections[i].status == CONN_HANDSHAKE_SENT) {
481 uint8_t temp_data[MAX_DATA_SIZE]; 498 uint8_t temp_data[MAX_DATA_SIZE];
482 uint8_t secret_nonce[crypto_box_NONCEBYTES]; 499 uint8_t secret_nonce[crypto_box_NONCEBYTES];
483 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 500 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
@@ -494,17 +511,17 @@ static void receive_crypto()
494 memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); 511 memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
495 increment_nonce(crypto_connections[i].sent_nonce); 512 increment_nonce(crypto_connections[i].sent_nonce);
496 uint32_t zero = 0; 513 uint32_t zero = 0;
497 crypto_connections[i].status = 3; /* connection status needs to be 3 for write_cryptpacket() to work */ 514 crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */
498 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); 515 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
499 crypto_connections[i].status = 2; /* set it to its proper value right after. */ 516 crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */
500 } 517 }
501 } 518 }
502 } else if (id_packet(crypto_connections[i].number) != -1) // This should not happen kill the connection if it does 519 } else if (id_packet(crypto_connections[i].number) != -1) // This should not happen kill the connection if it does
503 crypto_kill(crypto_connections[i].number); 520 crypto_kill(crypto_connections[i].number);
504 521
505 } 522 }
506 if (crypto_connections[i].status == 2) { 523 if (crypto_connections[i].status == CONN_NOT_CONFIRMED) {
507 if (id_packet(crypto_connections[i].number) == 3) { 524 if (id_packet(crypto_connections[i].number) == CONN_ESTABLISHED) {
508 uint8_t temp_data[MAX_DATA_SIZE]; 525 uint8_t temp_data[MAX_DATA_SIZE];
509 uint8_t data[MAX_DATA_SIZE]; 526 uint8_t data[MAX_DATA_SIZE];
510 int length = read_packet(crypto_connections[i].number, temp_data); 527 int length = read_packet(crypto_connections[i].number, temp_data);
@@ -514,7 +531,7 @@ static void receive_crypto()
514 uint32_t zero = 0; 531 uint32_t zero = 0;
515 if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { 532 if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) {
516 increment_nonce(crypto_connections[i].recv_nonce); 533 increment_nonce(crypto_connections[i].recv_nonce);
517 crypto_connections[i].status = 3; 534 crypto_connections[i].status = CONN_ESTABLISHED;
518 535
519 /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */ 536 /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
520 kill_connection_in(crypto_connections[i].number, 3000000); 537 kill_connection_in(crypto_connections[i].number, 3000000);
@@ -543,8 +560,8 @@ static void killTimedout()
543{ 560{
544 uint32_t i; 561 uint32_t i;
545 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 562 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
546 if (crypto_connections[i].status != 0 && is_connected(crypto_connections[i].number) == 4) 563 if (crypto_connections[i].status != CONN_NO_CONNECTION && is_connected(crypto_connections[i].number) == 4)
547 crypto_connections[i].status = 4; 564 crypto_connections[i].status = CONN_TIMED_OUT;
548 else if (is_connected(crypto_connections[i].number) == 4) { 565 else if (is_connected(crypto_connections[i].number) == 4) {
549 kill_connection(crypto_connections[i].number); 566 kill_connection(crypto_connections[i].number);
550 crypto_connections[i].number = ~0; 567 crypto_connections[i].number = ~0;
diff --git a/core/network.c b/core/network.c
index a7a4efcd..c58549bf 100644
--- a/core/network.c
+++ b/core/network.c
@@ -164,25 +164,42 @@ void shutdown_networking()
164 return; 164 return;
165} 165}
166 166
167/* resolves provided address to a binary data in network byte order 167/*
168 address is ASCII null terminated string 168 resolve_addr():
169 address should represent IPv4, IPv6 or a hostname 169 address should represent IPv4 or a hostname with A record
170 on success returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i 170
171 on failure returns -1 */ 171 returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i
172int resolve_addr(const char *address) 172 returns 0 on failure
173
174 TODO: Fix ipv6 support
175*/
176uint32_t resolve_addr(const char *address)
173{ 177{
174 struct addrinfo hints; 178 struct addrinfo *server = NULL;
179 struct addrinfo hints;
180 int rc;
181 uint32_t addr;
182
175 memset(&hints, 0, sizeof(hints)); 183 memset(&hints, 0, sizeof(hints));
176 hints.ai_family = AF_UNSPEC; //support both IPv4 and IPv6 184 hints.ai_family = AF_INET; // IPv4 only right now.
177 hints.ai_socktype = SOCK_DGRAM; //type of socket Tox uses 185 hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
178 186
179 struct addrinfo *server = NULL; 187 rc = getaddrinfo(address, "echo", &hints, &server);
180 188
181 int success = getaddrinfo(address, "echo", &hints, &server); 189 // Lookup failed.
182 if(success != 0) 190 if(rc != 0) {
183 return -1; 191 return 0;
192 }
193
194 // IPv4 records only..
195 if(server->ai_family != AF_INET) {
196 freeaddrinfo(server);
197 return 0;
198 }
199
200
201 addr = ((struct sockaddr_in*)server->ai_addr)->sin_addr.s_addr;
184 202
185 int resolved = ((struct sockaddr_in*)server->ai_addr)->sin_addr.s_addr;
186 freeaddrinfo(server); 203 freeaddrinfo(server);
187 return resolved; 204 return addr;
188} 205}
diff --git a/core/network.h b/core/network.h
index 3277070c..a7559ebe 100644
--- a/core/network.h
+++ b/core/network.h
@@ -57,6 +57,7 @@
57#include <sodium.h> 57#include <sodium.h>
58#else 58#else
59#include <crypto_box.h> 59#include <crypto_box.h>
60#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
60#endif 61#endif
61 62
62#ifdef __cplusplus 63#ifdef __cplusplus
@@ -116,12 +117,16 @@ int init_networking(IP ip, uint16_t port);
116/* function to cleanup networking stuff(doesn't do much right now) */ 117/* function to cleanup networking stuff(doesn't do much right now) */
117void shutdown_networking(); 118void shutdown_networking();
118 119
119/* resolves provided address to a binary data in network byte order 120/*
120 address is ASCII null terminated string 121 resolve_addr():
121 address should represent IPv4, IPv6 or a hostname 122 address should represent IPv4 or a hostname with A record
122 on success returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i 123
123 on failure returns -1 */ 124 returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i
124int resolve_addr(const char *address); 125 returns 0 on failure
126
127 TODO: Fix ipv6 support
128*/
129uint32_t resolve_addr(const char *address);
125 130
126#ifdef __cplusplus 131#ifdef __cplusplus
127} 132}
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
new file mode 100644
index 00000000..14126cfd
--- /dev/null
+++ b/docs/CMakeLists.txt
@@ -0,0 +1,40 @@
1# cmake should not fail if sphinx is missing
2find_package(Sphinx)
3
4if(SPHINX_EXECUTABLE)
5
6 if(NOT DEFINED SPHINX_THEME)
7 set(SPHINX_THEME default)
8 endif()
9
10 if(NOT DEFINED SPHINX_THEME_DIR)
11 set(SPHINX_THEME_DIR)
12 endif()
13
14 # configured documentation tools and intermediate build results
15 set(BINARY_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/_build")
16
17 # Sphinx cache with pickled ReST documents
18 set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees")
19
20 # HTML output directory
21 set(SPHINX_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/html")
22
23 configure_file(
24 "${CMAKE_CURRENT_SOURCE_DIR}/conf.py"
25 "${BINARY_BUILD_DIR}/conf.py"
26 @ONLY)
27
28 add_custom_target(docs
29 ${SPHINX_EXECUTABLE}
30 -b html
31 -c "${BINARY_BUILD_DIR}"
32 "${CMAKE_CURRENT_SOURCE_DIR}"
33 "${SPHINX_HTML_DIR}"
34 COMMENT "Building HTML documentation with Sphinx")
35else()
36 add_custom_target(docs
37 echo
38 "Please install python-sphinx to build the docs or read the docs online: https://projecttox.readthedocs.org/en/latest"
39 COMMENT "No sphinx executebale found")
40endif()
diff --git a/docs/commands.md b/docs/commands.md
deleted file mode 100644
index 8669bb9b..00000000
--- a/docs/commands.md
+++ /dev/null
@@ -1,25 +0,0 @@
1# Tox User Commands
2Here's a list of commands that nTox accepts,
3which can all be used by starting your line with
4a */*. Currently there can be no spaces before this.
5
6* */f* [ID]
7 + Add a friend with ID [ID].
8* */d*
9 + Call doMessenger() which does...something?
10* */m* \[FRIEND\_NUM\] \[MESSAGE\]
11 + Message \[FRIEND\_NUM\] \[MESSAGE\].
12* */n* \[NAME\]
13 + Change your username to \[NAME\].
14* */l*
15 + Print your list of friends. (like you have any)
16* */s* \[STATUS\]
17 + Set your status to \[STATUS\].
18* */a* \[ID\]
19 + Accept friend request from \[ID\].
20* */i*
21 + Print useful info about your client.
22* */h*
23 + Print some help.
24* */q/*
25 + Quit Tox. (why ;_;)
diff --git a/docs/commands.rst b/docs/commands.rst
new file mode 100644
index 00000000..45b50c83
--- /dev/null
+++ b/docs/commands.rst
@@ -0,0 +1,48 @@
1Tox User Commands
2=================
3
4Here's a list of commands that nTox accepts, which can all be used by
5starting your line with a */*. Currently there can be no spaces before
6this.
7
8- */f* [ID]
9
10 - Add a friend with ID [ID].
11
12- */d*
13
14 - Call doMessenger() which does...something?
15
16- */m* [FRIEND\_NUM] [MESSAGE]
17
18 - Message [FRIEND\_NUM] [MESSAGE].
19
20- */n* [NAME]
21
22 - Change your username to [NAME].
23
24- */l*
25
26 - Print your list of friends. (like you have any)
27
28- */s* [STATUS]
29
30 - Set your status to [STATUS].
31
32- */a* [ID]
33
34 - Accept friend request from [ID].
35
36- */i*
37
38 - Print useful info about your client.
39
40- */h*
41
42 - Print some help.
43
44- */q*
45
46 - Quit Tox.
47
48
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 00000000..afebb632
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,242 @@
1# -*- coding: utf-8 -*-
2#
3# ProjectTox documentation build configuration file, created by
4# sphinx-quickstart on Wed Jul 31 23:07:35 2013.
5#
6# This file is execfile()d with the current directory set to its containing dir.
7#
8# Note that not all possible configuration values are present in this
9# autogenerated file.
10#
11# All configuration values have a default; values that are commented out
12# serve to show the default.
13
14import sys, os
15
16# If extensions (or modules to document with autodoc) are in another directory,
17# add these directories to sys.path here. If the directory is relative to the
18# documentation root, use os.path.abspath to make it absolute, like shown here.
19#sys.path.insert(0, os.path.abspath('.'))
20
21# -- General configuration -----------------------------------------------------
22
23# If your documentation needs a minimal Sphinx version, state it here.
24#needs_sphinx = '1.0'
25
26# Add any Sphinx extension module names here, as strings. They can be extensions
27# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
28extensions = []
29
30# Add any paths that contain templates here, relative to this directory.
31templates_path = ['_templates']
32
33# The suffix of source filenames.
34source_suffix = '.rst'
35
36# The encoding of source files.
37#source_encoding = 'utf-8-sig'
38
39# The master toctree document.
40master_doc = 'index'
41
42# General information about the project.
43project = u'ProjectTox'
44copyright = u'2013, Tox Team'
45
46# The version info for the project you're documenting, acts as replacement for
47# |version| and |release|, also used in various other places throughout the
48# built documents.
49#
50# The short X.Y version.
51version = '0.1'
52# The full version, including alpha/beta/rc tags.
53release = '0.1'
54
55# The language for content autogenerated by Sphinx. Refer to documentation
56# for a list of supported languages.
57#language = None
58
59# There are two options for replacing |today|: either, you set today to some
60# non-false value, then it is used:
61#today = ''
62# Else, today_fmt is used as the format for a strftime call.
63#today_fmt = '%B %d, %Y'
64
65# List of patterns, relative to source directory, that match files and
66# directories to ignore when looking for source files.
67exclude_patterns = ['_build']
68
69# The reST default role (used for this markup: `text`) to use for all documents.
70#default_role = None
71
72# If true, '()' will be appended to :func: etc. cross-reference text.
73#add_function_parentheses = True
74
75# If true, the current module name will be prepended to all description
76# unit titles (such as .. function::).
77#add_module_names = True
78
79# If true, sectionauthor and moduleauthor directives will be shown in the
80# output. They are ignored by default.
81#show_authors = False
82
83# The name of the Pygments (syntax highlighting) style to use.
84pygments_style = 'sphinx'
85
86# A list of ignored prefixes for module index sorting.
87#modindex_common_prefix = []
88
89
90# -- Options for HTML output ---------------------------------------------------
91
92# The theme to use for HTML and HTML Help pages. See the documentation for
93# a list of builtin themes.
94html_theme = 'default'
95
96# Theme options are theme-specific and customize the look and feel of a theme
97# further. For a list of options available for each theme, see the
98# documentation.
99#html_theme_options = {}
100
101# Add any paths that contain custom themes here, relative to this directory.
102#html_theme_path = []
103
104# The name for this set of Sphinx documents. If None, it defaults to
105# "<project> v<release> documentation".
106#html_title = None
107
108# A shorter title for the navigation bar. Default is the same as html_title.
109#html_short_title = None
110
111# The name of an image file (relative to this directory) to place at the top
112# of the sidebar.
113#html_logo = None
114
115# The name of an image file (within the static path) to use as favicon of the
116# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
117# pixels large.
118#html_favicon = None
119
120# Add any paths that contain custom static files (such as style sheets) here,
121# relative to this directory. They are copied after the builtin static files,
122# so a file named "default.css" will overwrite the builtin "default.css".
123html_static_path = ['_static']
124
125# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
126# using the given strftime format.
127#html_last_updated_fmt = '%b %d, %Y'
128
129# If true, SmartyPants will be used to convert quotes and dashes to
130# typographically correct entities.
131#html_use_smartypants = True
132
133# Custom sidebar templates, maps document names to template names.
134#html_sidebars = {}
135
136# Additional templates that should be rendered to pages, maps page names to
137# template names.
138#html_additional_pages = {}
139
140# If false, no module index is generated.
141#html_domain_indices = True
142
143# If false, no index is generated.
144#html_use_index = True
145
146# If true, the index is split into individual pages for each letter.
147#html_split_index = False
148
149# If true, links to the reST sources are added to the pages.
150#html_show_sourcelink = True
151
152# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
153#html_show_sphinx = True
154
155# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
156#html_show_copyright = True
157
158# If true, an OpenSearch description file will be output, and all pages will
159# contain a <link> tag referring to it. The value of this option must be the
160# base URL from which the finished HTML is served.
161#html_use_opensearch = ''
162
163# This is the file name suffix for HTML files (e.g. ".xhtml").
164#html_file_suffix = None
165
166# Output file base name for HTML help builder.
167htmlhelp_basename = 'ProjectToxdoc'
168
169
170# -- Options for LaTeX output --------------------------------------------------
171
172latex_elements = {
173# The paper size ('letterpaper' or 'a4paper').
174#'papersize': 'letterpaper',
175
176# The font size ('10pt', '11pt' or '12pt').
177#'pointsize': '10pt',
178
179# Additional stuff for the LaTeX preamble.
180#'preamble': '',
181}
182
183# Grouping the document tree into LaTeX files. List of tuples
184# (source start file, target name, title, author, documentclass [howto/manual]).
185latex_documents = [
186 ('index', 'ProjectTox.tex', u'ProjectTox Documentation',
187 u'Tox Team', 'manual'),
188]
189
190# The name of an image file (relative to this directory) to place at the top of
191# the title page.
192#latex_logo = None
193
194# For "manual" documents, if this is true, then toplevel headings are parts,
195# not chapters.
196#latex_use_parts = False
197
198# If true, show page references after internal links.
199#latex_show_pagerefs = False
200
201# If true, show URL addresses after external links.
202#latex_show_urls = False
203
204# Documents to append as an appendix to all manuals.
205#latex_appendices = []
206
207# If false, no module index is generated.
208#latex_domain_indices = True
209
210
211# -- Options for manual page output --------------------------------------------
212
213# One entry per manual page. List of tuples
214# (source start file, name, description, authors, manual section).
215man_pages = [
216 ('index', 'projecttox', u'ProjectTox Documentation',
217 [u'Tox Team'], 1)
218]
219
220# If true, show URL addresses after external links.
221#man_show_urls = False
222
223
224# -- Options for Texinfo output ------------------------------------------------
225
226# Grouping the document tree into Texinfo files. List of tuples
227# (source start file, target name, title, author,
228# dir menu entry, description, category)
229texinfo_documents = [
230 ('index', 'ProjectTox', u'ProjectTox Documentation',
231 u'Tox Team', 'ProjectTox', 'One line description of project.',
232 'Miscellaneous'),
233]
234
235# Documents to append as an appendix to all manuals.
236#texinfo_appendices = []
237
238# If false, no module index is generated.
239#texinfo_domain_indices = True
240
241# How to display URL addresses: 'footnote', 'no', or 'inline'.
242#texinfo_show_urls = 'footnote'
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 00000000..10e0d1d2
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,25 @@
1.. ProjectTox documentation master file, created by
2 sphinx-quickstart on Wed Jul 31 23:07:35 2013.
3 You can adapt this file completely to your liking, but it should at least
4 contain the root `toctree` directive.
5
6Welcome to ProjectTox's documentation!
7======================================
8
9Contents:
10
11.. toctree::
12 start_guide.rst
13 install.rst
14 commands.rst
15 :maxdepth: 2
16
17
18
19Indices and tables
20==================
21
22* :ref:`genindex`
23* :ref:`modindex`
24* :ref:`search`
25
diff --git a/docs/install.rst b/docs/install.rst
new file mode 100644
index 00000000..c5fea5d1
--- /dev/null
+++ b/docs/install.rst
@@ -0,0 +1,129 @@
1Install Instructions
2====================
3
4Linux
5---------
6
7First, install the build dependencies ::
8
9 bash apt-get install build-essential libtool autotools-dev automake libconfig-dev ncurses-dev cmake checkinstall
10
11.. note :: ``libconfig-dev`` should be >= 1.4.
12
13
14Then you'll need a recent version of `libsodium <https://github.com/jedisct1/libsodium>`_ ::
15
16 git clone git://github.com/jedisct1/libsodium.git
17 cd libsodium
18 git checkout tags/0.4.2
19 ./autogen.sh
20 ./configure && make check
21 sudo checkinstall --install --pkgname libsodium --pkgversion 0.4.2 --nodoc
22 sudo ldconfig``
23
24Finally, fetch the Tox source code and run cmake ::
25
26 git clone git://github.com/irungentoo/ProjectTox-Core.git
27 cd ProjectTox-Core && mkdir build && cd build
28 cmake ..
29
30Then you can build any of the files in `/testing`_ and `/other`_ that are currently
31supported on your platform by running ::
32
33 make name_of_c_file
34
35For example, to build `Messenger_test.c`_ you would run ::
36
37 make Messenger_test
38
39
40Or you could just build everything that is supported on your platform by
41running ::
42 bash make
43
44OS X
45------
46
47Homebrew
48~~~~~~~~~~
49::
50
51 brew install libtool automake autoconf libconfig libsodium cmake
52 cmake .
53 make
54 sudo make install
55
56Non-homebrew
57~~~~~~~~~~~~
58
59Much the same as Linux, remember to install the latest XCode and the
60developer tools (Preferences -> Downloads -> Command Line Tools). Users
61running Mountain Lion and the latest version of XCode (4.6.3) will also
62need to install libtool, automake and autoconf. They are easy enough to
63install, grab them from http://www.gnu.org/software/libtool/,
64http://www.gnu.org/software/autoconf/ and
65http://www.gnu.org/software/automake/, then follow these steps for each:
66
67::
68
69 ./configure
70 make
71 sudo make install
72
73Do not install them from macports (or any dependencies for that matter)
74as they get shoved in the wrong directory and make your life more
75annoying.
76
77Another thing you may want to install is the latest gcc, this caused me
78a few problems as XCode from 4.3 no longer includes gcc and instead uses
79LLVM-GCC, a nice install guide can be found at
80http://caiustheory.com/install-gcc-421-apple-build-56663-with-xcode-42
81
82Windows
83---------
84
85You should install:
86
87* `MinGW <http://sourceforge.net/projects/mingw/>`_'s C compiler
88* `CMake <http://www.cmake.org/cmake/resources/software.html>`_
89
90You have to `modify your PATH environment
91variable <http://www.computerhope.com/issues/ch000549.htm>`_ so that it
92contains MinGW's bin folder path. With default settings, the bin folder
93is located at ``C:\MinGW\bin``, which means that you would have to
94append ``;C:\MinGW\bin`` to the PATH variable.
95
96Then you should either clone this repo by using git, or just download a
97`zip of current Master
98branch <https://github.com/irungentoo/ProjectTox-Core/archive/master.zip>`_
99and extract it somewhere.
100
101After that you should get precompiled package of libsodium from
102`here <https://download.libsodium.org/libsodium/releases/libsodium-win32-0.4.2.tar.gz>`_
103and extract the archive into this repo's root. That is, ``sodium``
104folder should be along with ``core``, ``testing`` and other folders.
105
106Navigate in ``cmd`` to this repo and run::
107
108 mkdir build && cd build
109 cmake -G "MinGW Makefiles" ..
110
111Then you can build any of the `/testing`_ and `/other`_ that are currently
112supported on your platform by running::
113
114 mingw32-make name_of_c_file
115
116For example, to build `Messenger_test.c`_ you would run::
117
118 mingw32-make Messenger_test``
119
120Or you could just build everything that is supported on your platform by
121running::
122
123 mingw32-make
124
125
126.. _/testing: https://github.com/irungentoo/ProjectTox-Core/tree/master/testing
127.. _/other: https://github.com/irungentoo/ProjectTox-Core/tree/master/other
128
129.. _Messenger_test.c: https://github.com/irungentoo/ProjectTox-Core/tree/master/other/Messanger_test.c
diff --git a/docs/start_guide.de.rst b/docs/start_guide.de.rst
new file mode 100644
index 00000000..4ebe7dc6
--- /dev/null
+++ b/docs/start_guide.de.rst
@@ -0,0 +1,66 @@
1Tox nutzen
2==========
3
41. :doc:`Tox erstellen <install>`
52. Fehler korrigieren
63. Im IRC nach Hilfe fragen
74. Auf Debug-Reise für Entwickler
85. Tox wirklich erstellen
96. ???
10
11Trotz der ganzen Arbeit, die wir bisher in Tox gesteckt haben, gibt es
12noch keine richtige Anleitung, wie man Tox *benutzt*. Dies ist ein
13anwenderfreundlicher Versuch.
14
151. Verbinde dich zum Netzwerk!
16
17 - Du musst dich zu einem Bootstrap-Server verbinden, um einen
18 öffentlichen Schlüssel zu erhalten.
19 - Wo finde ich einen öffentlichen Server? Zur Zeit hier: (die
20 Hilfe-Nachricht von nTox ohne Kommandos hilft auch)
21
22 - 198.46.136.167 33445
23 728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854
24 - 192.81.133.111 33445
25 8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858
26 - 66.175.223.88 33445
27 AC4112C975240CAD260BB2FCD134266521FAAF0A5D159C5FD3201196191E4F5D
28 - 192.184.81.118 33445
29 5CD7EB176C19A2FD840406CD56177BB8E75587BB366F7BB3004B19E3EDC04143
30
312. Finde einen Freund!
32
33 - Jetzt, da du im Netzwerk bist, brauchst du einen Freund. Um einen
34 zu bekommen, musst du eine Anfrage senden oder erhalten. Was eine
35 Anfrage ist? Es ist wie eine Freundschaftsanfrage, jedoch benutzen
36 wir unglaublich schaurige und kryptische Nummern anstatt Namen.
37 When nTox startet, erscheint *deine* lange, schaurige Nummer, auch
38 *öffentlicher Schlüssel* genannt. Diesen kannst du an andere
39 Personen weitergeben und sie können dich als "Freund" hinzufügen.
40 Oder du fügst andere Personen mit dem */f*-Befehl hinzu, wenn du
41 möchtest.
42
433. Chatte drauf los!
44
45 - Benutze nun den */m*-Befehl, um eine Nachricht an jemanden zu
46 senden. Wow, du chattest!
47
484. Mach etwas kaputt!
49
50 - Jep, pre-alpha-alpha-Software stürzt manchmal ab. Wir arbeiten
51 daran.
52 - Bitte melde alle Abstürze entweder an die GitHub-Seite oder
53 #tox-dev im freenode-IRC.
54
555. Nichts ist kaputt, aber was bedeutet */f*?
56
57 - nTox liest einen Text als Befehl, wenn das erste Zeichen ein
58 Schrägstrich ist ('/'). Du kannst alle Befehle in commands.md
59 nachlesen.
60
616. Benutze und unterstütze Tox!
62
63 - Programmiere, debugge, dokumentiere, übersetze für uns, oder
64 sprich einfach über uns!
65 - Je mehr Interesse wir erhalten, desto mehr Arbeit wird getan und
66 desto besser wird Tox.
diff --git a/docs/start_guide.rst b/docs/start_guide.rst
new file mode 100644
index 00000000..19ef982e
--- /dev/null
+++ b/docs/start_guide.rst
@@ -0,0 +1,63 @@
1Using Tox
2=========
3
4.. note:: There is a German version of this page available: :doc:`start_guide.de`
5
6
71. :doc:`Build Tox <install>`
82. Fix errors
93. Consult IRC for help
104. Go on debugging journey for devs
115. Build Tox for real
126. ???
13
14For all the work we've put into Tox so far, there isn't yet a decent
15guide for how you *use* Tox. Here's a user-friendly attempt at it.
16
171. Connect to the network!
18
19 - You need to connect to a bootstrapping server, to give you a
20 public key.
21 - Where can I find a public server? Right here, as of now: (the help
22 message from running ``nTox`` with no args will help)
23
24 - ``198.46.136.167 33445 728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854``
25 - ``192.81.133.111 33445 8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858``
26 - ``66.175.223.88 33445 AC4112C975240CAD260BB2FCD134266521FAAF0A5D159C5FD3201196191E4F5D``
27 - ``192.184.81.118 33445 5CD7EB176C19A2FD840406CD56177BB8E75587BB366F7BB3004B19E3EDC04143``
28
292. Find a friend!
30
31 - Now that you're on the network, you need a friend. To get one of
32 those, you need to to send or receive a request. What's a request,
33 you ask? It's like a friend request, but we use really scary and
34 cryptic numbers instead of names. When ``nTox`` starts, it shows
35 *your* long, scary number, called your *public key*. Give that to
36 people, and they can add you as a "friend". Or, you can add
37 someone else, with the ``/f`` command, if you like.
38
393. Chat it up!
40
41 - Now use the ``/m`` command to send a message to someone. Wow,
42 you're chatting!
43
444. But something broke!
45
46 - Yeah, pre-alpha-alpha software tends to do that. We're working on
47 it.
48 - Please report all crashes to either the GitHub page, or
49 ``#tox-dev`` on freenode.
50
515. Nothing broke, but what does ``/f`` mean?
52
53 - ``nTox`` parses text as a command if the first character is a
54 forward-slash (``/``). You can check all commands in commands.md.
55
566. Use and support Tox!
57
58 - Code for us, debug for us, document for us, translate for us, even
59 just talk about us!
60 - The more interest we get, the more work gets done, the better Tox
61 is.
62
63
diff --git a/docs/using_tox.md b/docs/using_tox.md
deleted file mode 100644
index b4f4310d..00000000
--- a/docs/using_tox.md
+++ /dev/null
@@ -1,38 +0,0 @@
1# Using Tox
21. Build Tox
32. Fix errors
43. Consult IRC for help
54. Go on debugging journy for devs
65. Build Tox for real
76. ???
8
9For all the work we've put into Tox so far,
10there isn't yet a decent guide for how you _use_
11Tox. Here's a user-friendly attempt at it.
12
131. Connect to the network!
14 + You need to connect to a bootstrapping server, to give you a public key.
15 + Where can I find a public server? Right here, as of now:
16 (the help message from running nTox with no args will help)
17 + 198.46.136.167 33445 728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854
18 + 192.81.133.111 33445 8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858
19 + 66.175.223.88 33445 AC4112C975240CAD260BB2FCD134266521FAAF0A5D159C5FD3201196191E4F5D
20 + 192.184.81.118 33445 5CD7EB176C19A2FD840406CD56177BB8E75587BB366F7BB3004B19E3EDC04143
212. Find a friend!
22 + Now that you're on the network, you need a friend. To get one of those,
23 you need to to send or receive a request. What's a request, you ask?
24 It's like a friend request, but we use really scary and cryptic numbers
25 instead of names. When nTox starts, it shows your _your_ long, scary number,
26 called your *public key*. Give that to people, and they can add you as
27 as "friend". Or, you can add someone else, with the */f* command, if you like.
283. Chat it up!
29 + Now use the */m* command to send a message to someone. Wow, you're chatting!
304. But something broke!
31 + Yeah, pre-alpha-alpha software tends to do that. We're working on it.
32 + Please report all crashes to either the github page, or #tox-dev on freenode.
335. Nothing broke, but what does */f* mean?
34 + nTox parses text as a command if the first character is a forward-slash ('/').
35 You can check all commands in commands.md.
366. Use and support Tox!
37 + Code for us, debug for us, document for us, translate for us, even just talk about us!
38 + The more interest we get, the more work gets done, the better Tox is.
diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
index 4f28fb3c..48152744 100644
--- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
+++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
@@ -245,7 +245,7 @@ struct server_conf_s configure_server(char *cfg_file)
245 it away in the server_info struct */ 245 it away in the server_info struct */
246 server_conf.info[i].valid = 1; 246 server_conf.info[i].valid = 1;
247 247
248 if(resolve_addr(strcpy(tmp_ip, bs_ip)) == -1) { 248 if(resolve_addr(strcpy(tmp_ip, bs_ip)) == 0) {
249 server_conf.info[i].valid = 0; 249 server_conf.info[i].valid = 0;
250 printf("bootstrap_server %d: Invalid IP\n", i); 250 printf("bootstrap_server %d: Invalid IP\n", i);
251 } 251 }
diff --git a/start_guide.de.md b/start_guide.de.md
deleted file mode 100644
index 7dfd52ca..00000000
--- a/start_guide.de.md
+++ /dev/null
@@ -1,40 +0,0 @@
1# Tox nutzen
21. Tox erstellen
32. Fehler korrigieren
43. Im IRC nach Hilfe fragen
54. Auf Debug-Reise für Entwickler
65. Tox wirklich erstellen
76. ???
8
9Trotz der ganzen Arbeit, die wir bisher in Tox
10gesteckt haben, gibt es noch keine richtige
11Anleitung, wie man Tox _benutzt_.
12Dies ist ein anwenderfreundlicher Versuch.
13
141. Verbinde dich zum Netzwerk!
15 + Du musst dich zu einem Bootstrap-Server verbinden, um einen öffentlichen Schlüssel zu erhalten.
16 + Wo finde ich einen öffentlichen Server? Zur Zeit hier:
17 (die Hilfe-Nachricht von nTox ohne Kommandos hilft auch)
18 + 198.46.136.167 33445 728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854
19 + 192.81.133.111 33445 8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858
20 + 66.175.223.88 33445 AC4112C975240CAD260BB2FCD134266521FAAF0A5D159C5FD3201196191E4F5D
21 + 192.184.81.118 33445 5CD7EB176C19A2FD840406CD56177BB8E75587BB366F7BB3004B19E3EDC04143
222. Finde einen Freund!
23 + Jetzt, da du im Netzwerk bist, brauchst du einen Freund. Um einen zu bekommen,
24 musst du eine Anfrage senden oder erhalten. Was eine Anfrage ist?
25 Es ist wie eine Freundschaftsanfrage, jedoch benutzen wir unglaublich schaurige
26 und kryptische Nummern anstatt Namen. When nTox startet, erscheint _deine_ lange,
27 schaurige Nummer, auch *öffentlicher Schlüssel* genannt. Diesen kannst du an
28 andere Personen weitergeben und sie können dich als "Freund" hinzufügen. Oder du
29 fügst andere Personen mit dem */f*-Befehl hinzu, wenn du möchtest.
303. Chatte drauf los!
31 + Benutze nun den */m*-Befehl, um eine Nachricht an jemanden zu senden. Wow, du chattest!
324. Mach etwas kaputt!
33 + Jep, pre-alpha-alpha-Software stürzt manchmal ab. Wir arbeiten daran.
34 + Bitte melde alle Abstürze entweder an die GitHub-Seite oder #tox-dev im freenode-IRC.
355. Nichts ist kaputt, aber was bedeutet */f*?
36 + nTox liest einen Text als Befehl, wenn das erste Zeichen ein Schrägstrich ist ('/').
37 Du kannst alle Befehle in commands.md nachlesen.
386. Benutze und unterstütze Tox!
39 + Programmiere, debugge, dokumentiere, übersetze für uns, oder sprich einfach über uns!
40 + Je mehr Interesse wir erhalten, desto mehr Arbeit wird getan und desto besser wird Tox.
diff --git a/start_guide.md b/start_guide.md
deleted file mode 100644
index 31d7ca8e..00000000
--- a/start_guide.md
+++ /dev/null
@@ -1,38 +0,0 @@
1# Using Tox
21. [Build Tox](/INSTALL.md)
32. Fix errors
43. Consult IRC for help
54. Go on debugging journy for devs
65. Build Tox for real
76. ???
8
9For all the work we've put into Tox so far,
10there isn't yet a decent guide for how you _use_
11Tox. Here's a user-friendly attempt at it.
12
131. Connect to the network!
14 + You need to connect to a bootstrapping server, to give you a public key.
15 + Where can I find a public server? Right here, as of now:
16 (the help message from running `nTox` with no args will help)
17 + `198.46.136.167 33445 728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854`
18 + `192.81.133.111 33445 8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858`
19 + `66.175.223.88 33445 AC4112C975240CAD260BB2FCD134266521FAAF0A5D159C5FD3201196191E4F5D`
20 + `192.184.81.118 33445 5CD7EB176C19A2FD840406CD56177BB8E75587BB366F7BB3004B19E3EDC04143`
212. Find a friend!
22 + Now that you're on the network, you need a friend. To get one of those,
23 you need to to send or receive a request. What's a request, you ask?
24 It's like a friend request, but we use really scary and cryptic numbers
25 instead of names. When `nTox` starts, it shows your _your_ long, scary number,
26 called your *public key*. Give that to people, and they can add you as
27 as "friend". Or, you can add someone else, with the `/f` command, if you like.
283. Chat it up!
29 + Now use the `/m` command to send a message to someone. Wow, you're chatting!
304. But something broke!
31 + Yeah, pre-alpha-alpha software tends to do that. We're working on it.
32 + Please report all crashes to either the [github](/) page, or `#tox-dev` on freenode.
335. Nothing broke, but what does `/f` mean?
34 + `nTox` parses text as a command if the first character is a forward-slash (`/`).
35 You can check all commands in commands.md.
366. Use and support Tox!
37 + Code for us, debug for us, document for us, translate for us, even just talk about us!
38 + The more interest we get, the more work gets done, the better Tox is.
diff --git a/testing/DHT_test.c b/testing/DHT_test.c
index 588450e2..f1940614 100644
--- a/testing/DHT_test.c
+++ b/testing/DHT_test.c
@@ -60,11 +60,11 @@ void print_clientlist()
60 } 60 }
61 p_ip = close_clientlist[i].ip_port; 61 p_ip = close_clientlist[i].ip_port;
62 printf("\nIP: %u.%u.%u.%u Port: %u",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); 62 printf("\nIP: %u.%u.%u.%u Port: %u",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port));
63 printf("\nTimestamp: %u", close_clientlist[i].timestamp); 63 printf("\nTimestamp: %llu",(long long unsigned int) close_clientlist[i].timestamp);
64 printf("\nLast pinged: %u\n", close_clientlist[i].last_pinged); 64 printf("\nLast pinged: %llu\n",(long long unsigned int) close_clientlist[i].last_pinged);
65 p_ip = close_clientlist[i].ret_ip_port; 65 p_ip = close_clientlist[i].ret_ip_port;
66 printf("OUR IP: %u.%u.%u.%u Port: %u\n",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); 66 printf("OUR IP: %u.%u.%u.%u Port: %u\n",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port));
67 printf("Timestamp: %u\n", close_clientlist[i].ret_timestamp); 67 printf("Timestamp: %llu\n",(long long unsigned int) close_clientlist[i].ret_timestamp);
68 } 68 }
69} 69}
70 70
@@ -93,11 +93,11 @@ void print_friendlist()
93 } 93 }
94 p_ip = friends_list[k].client_list[i].ip_port; 94 p_ip = friends_list[k].client_list[i].ip_port;
95 printf("\nIP: %u.%u.%u.%u:%u",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); 95 printf("\nIP: %u.%u.%u.%u:%u",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port));
96 printf("\nTimestamp: %u", friends_list[k].client_list[i].timestamp); 96 printf("\nTimestamp: %llu",(long long unsigned int) friends_list[k].client_list[i].timestamp);
97 printf("\nLast pinged: %u\n", friends_list[k].client_list[i].last_pinged); 97 printf("\nLast pinged: %llu\n",(long long unsigned int) friends_list[k].client_list[i].last_pinged);
98 p_ip = friends_list[k].client_list[i].ret_ip_port; 98 p_ip = friends_list[k].client_list[i].ret_ip_port;
99 printf("ret IP: %u.%u.%u.%u:%u\n",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); 99 printf("ret IP: %u.%u.%u.%u:%u\n",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port));
100 printf("Timestamp: %u\n", friends_list[k].client_list[i].ret_timestamp); 100 printf("Timestamp: %llu\n", (long long unsigned int)friends_list[k].client_list[i].ret_timestamp);
101 } 101 }
102 } 102 }
103} 103}
diff --git a/testing/nTox.c b/testing/nTox.c
index 17f4b0e7..13db58d7 100644
--- a/testing/nTox.c
+++ b/testing/nTox.c
@@ -18,7 +18,7 @@
18 * 18 *
19 * You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 20 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21 * 21 *
22 */ 22 */
23#include "nTox.h" 23#include "nTox.h"
24#include "misc_tools.h" 24#include "misc_tools.h"
@@ -44,13 +44,37 @@ int x, y;
44uint8_t pending_requests[256][CLIENT_ID_SIZE]; 44uint8_t pending_requests[256][CLIENT_ID_SIZE];
45uint8_t num_requests = 0; 45uint8_t num_requests = 0;
46 46
47void get_id(char *data)
48{
49 char idstring0[200];
50 char idstring1[PUB_KEY_BYTES][5];
51 char idstring2[PUB_KEY_BYTES][5];
52 int i = 0;
53 for(i = 0; i < PUB_KEY_BYTES; i++)
54 {
55 if (self_public_key[i] < (PUB_KEY_BYTES / 2))
56 strcpy(idstring1[i],"0");
57 else
58 strcpy(idstring1[i], "");
59 sprintf(idstring2[i], "%hhX",self_public_key[i]);
60 }
61 strcpy(idstring0,"[i] ID: ");
62 int j = 0;
63 for (j = 0; j < PUB_KEY_BYTES; j++) {
64 strcat(idstring0,idstring1[j]);
65 strcat(idstring0,idstring2[j]);
66 }
67
68 memcpy(data, idstring0, strlen(idstring0));
69}
70
47void new_lines(char *line) 71void new_lines(char *line)
48{ 72{
49 int i; 73 int i = 0;
50 for (i = HISTORY-1; i > 0; i--) 74 for (i = HISTORY-1; i > 0; i--)
51 strcpy(lines[i], lines[i-1]); 75 strncpy(lines[i], lines[i-1], STRING_LENGTH - 1);
52 76
53 strcpy(lines[0], line); 77 strncpy(lines[0], line, STRING_LENGTH - 1);
54 do_refresh(); 78 do_refresh();
55} 79}
56 80
@@ -89,7 +113,12 @@ char *format_message(char *message, int friendnum)
89 char* time = asctime(timeinfo); 113 char* time = asctime(timeinfo);
90 size_t len = strlen(time); 114 size_t len = strlen(time);
91 time[len-1] = '\0'; 115 time[len-1] = '\0';
92 sprintf(msg, "[%d] %s <%s> %s", friendnum, time, name, message); // timestamp 116 if (friendnum != -1) {
117 sprintf(msg, "[%d] %s <%s> %s", friendnum, time, name, message);
118 } else {
119 // This message came from ourselves
120 sprintf(msg, "%s <%s> %s", time, name, message);
121 }
93 return msg; 122 return msg;
94} 123}
95 124
@@ -104,26 +133,30 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
104 if (inpt_command == 'f') { // add friend command: /f ID 133 if (inpt_command == 'f') { // add friend command: /f ID
105 int i; 134 int i;
106 char temp_id[128]; 135 char temp_id[128];
107 for (i = 0; i < 128; i++) 136 for (i = 0; i < 128; i++)
108 temp_id[i] = line[i+prompt_offset]; 137 temp_id[i] = line[i+prompt_offset];
138
109 int num = m_addfriend(hex_string_to_bin(temp_id), (uint8_t*)"Install Gentoo", sizeof("Install Gentoo")); 139 int num = m_addfriend(hex_string_to_bin(temp_id), (uint8_t*)"Install Gentoo", sizeof("Install Gentoo"));
110 char numstring[100]; 140 char numstring[100];
111 switch (num) { 141 switch (num) {
112 case -1: 142 case -1:
113 sprintf(numstring, "[i] Incorrect key length"); 143 sprintf(numstring, "[i] Message is too long.");
114 break; 144 break;
115 case -2: 145 case -2:
116 sprintf(numstring, "[i] That appears to be your own key"); 146 sprintf(numstring, "[i] Please add a message to your request.");
117 break; 147 break;
118 case -3: 148 case -3:
119 sprintf(numstring, "[i] Friend request already sent"); 149 sprintf(numstring, "[i] That appears to be your own ID.");
120 break; 150 break;
121 case -4: 151 case -4:
122 sprintf(numstring, "[i] Could not add friend"); 152 sprintf(numstring, "[i] Friend request already sent.");
123 break; 153 break;
124 default: 154 case -5:
125 sprintf(numstring, "[i] Added friend %d", num); 155 sprintf(numstring, "[i] Undefined error when adding friend.");
126 break; 156 break;
157 default:
158 sprintf(numstring, "[i] Added friend as %d.", num);
159 break;
127 } 160 }
128 new_lines(numstring); 161 new_lines(numstring);
129 do_refresh(); 162 do_refresh();
@@ -133,6 +166,9 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
133 } 166 }
134 else if (inpt_command == 'm') { //message command: /m friendnumber messsage 167 else if (inpt_command == 'm') { //message command: /m friendnumber messsage
135 size_t len = strlen(line); 168 size_t len = strlen(line);
169 if(len < 3)
170 return;
171
136 char numstring[len-3]; 172 char numstring[len-3];
137 char message[len-3]; 173 char message[len-3];
138 int i; 174 int i;
@@ -141,13 +177,13 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
141 numstring[i] = line[i+3]; 177 numstring[i] = line[i+3];
142 } else { 178 } else {
143 int j; 179 int j;
144 for (j = (i+1); j < len; j++) 180 for (j = (i+1); j < (len+1); j++)
145 message[j-i-1] = line[j+3]; 181 message[j-i-1] = line[j+3];
146 break; 182 break;
147 } 183 }
148 } 184 }
149 int num = atoi(numstring); 185 int num = atoi(numstring);
150 if (m_sendmessage(num, (uint8_t*) message, sizeof(message)) != 1) { 186 if (m_sendmessage(num, (uint8_t*) message, strlen(message) + 1) != 1) {
151 new_lines("[i] could not send message"); 187 new_lines("[i] could not send message");
152 } else { 188 } else {
153 new_lines(format_message(message, -1)); 189 new_lines(format_message(message, -1));
@@ -162,7 +198,7 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
162 name[i-3] = line[i]; 198 name[i-3] = line[i];
163 } 199 }
164 name[i-3] = 0; 200 name[i-3] = 0;
165 setname(name, i); 201 setname(name, i - 2);
166 char numstring[100]; 202 char numstring[100];
167 sprintf(numstring, "[i] changed nick to %s", (char*)name); 203 sprintf(numstring, "[i] changed nick to %s", (char*)name);
168 new_lines(numstring); 204 new_lines(numstring);
@@ -179,7 +215,7 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
179 status[i-3] = line[i]; 215 status[i-3] = line[i];
180 } 216 }
181 status[i-3] = 0; 217 status[i-3] = 0;
182 m_set_userstatus(status, strlen((char*)status)); 218 m_set_userstatus(status, strlen((char*)status) + 1);
183 char numstring[100]; 219 char numstring[100];
184 sprintf(numstring, "[i] changed status to %s", (char*)status); 220 sprintf(numstring, "[i] changed status to %s", (char*)status);
185 new_lines(numstring); 221 new_lines(numstring);
@@ -204,32 +240,15 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
204 new_lines("[i] /l list (list friends), /h for help, /i for info, /n nick (to change nickname), /q (to quit)"); 240 new_lines("[i] /l list (list friends), /h for help, /i for info, /n nick (to change nickname), /q (to quit)");
205 } 241 }
206 else if (inpt_command == 'i') { //info 242 else if (inpt_command == 'i') { //info
207 char idstring0[200]; 243 char idstring[200];
208 char idstring1[PUB_KEY_BYTES][5]; 244 get_id(idstring);
209 char idstring2[PUB_KEY_BYTES][5]; 245 new_lines(idstring);
210 int i;
211 for (i = 0; i < PUB_KEY_BYTES; i++)
212 {
213 if (self_public_key[i] < (PUB_KEY_BYTES/2))
214 strcpy(idstring1[i],"0");
215 else
216 strcpy(idstring1[i], "");
217 sprintf(idstring2[i], "%hhX", self_public_key[i]);
218 }
219 //
220 strcpy(idstring0,"[i] ID: ");
221 int j;
222 for (j = 0; j < PUB_KEY_BYTES; j++) {
223 strcat(idstring0,idstring1[j]);
224 strcat(idstring0,idstring2[j]);
225 }
226 new_lines(idstring0);
227 } 246 }
228 247
229 else if (inpt_command == 'q') { //exit 248 else if (inpt_command == 'q') { //exit
230 endwin(); 249 endwin();
231 exit(EXIT_SUCCESS); 250 exit(EXIT_SUCCESS);
232 } else { 251 } else {
233 new_lines("[i] invalid command"); 252 new_lines("[i] invalid command");
234 } 253 }
235 } else { 254 } else {
@@ -313,21 +332,10 @@ void print_request(uint8_t *public_key, uint8_t *data, uint16_t length)
313 332
314void print_message(int friendnumber, uint8_t * string, uint16_t length) 333void print_message(int friendnumber, uint8_t * string, uint16_t length)
315{ 334{
316 char name[MAX_NAME_LENGTH];
317 getname(friendnumber, (uint8_t*)name);
318 char msg[100+length+strlen(name)+1];
319 time_t rawtime;
320 struct tm * timeinfo;
321 time ( &rawtime );
322 timeinfo = localtime ( &rawtime );
323 char* temp = asctime(timeinfo);
324 size_t len = strlen(temp);
325 temp[len-1] = '\0';
326 sprintf(msg, "[%d] %s <%s> %s", friendnumber, temp, name, string); // timestamp
327 new_lines(format_message((char*)string, friendnumber)); 335 new_lines(format_message((char*)string, friendnumber));
328} 336}
329 337
330void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) 338void print_nickchange(int friendnumber, uint8_t *string, uint16_t length)
331{ 339{
332 char name[MAX_NAME_LENGTH]; 340 char name[MAX_NAME_LENGTH];
333 getname(friendnumber, (uint8_t*)name); 341 getname(friendnumber, (uint8_t*)name);
@@ -336,7 +344,7 @@ void print_nickchange(int friendnumber, uint8_t *string, uint16_t length)
336 new_lines(msg); 344 new_lines(msg);
337} 345}
338 346
339void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) 347void print_statuschange(int friendnumber, uint8_t *string, uint16_t length)
340{ 348{
341 char name[MAX_NAME_LENGTH]; 349 char name[MAX_NAME_LENGTH];
342 getname(friendnumber, (uint8_t*)name); 350 getname(friendnumber, (uint8_t*)name);
@@ -345,7 +353,7 @@ void print_statuschange(int friendnumber, uint8_t *string, uint16_t length)
345 new_lines(msg); 353 new_lines(msg);
346} 354}
347 355
348void load_key() 356void load_key()
349{ 357{
350 FILE *data_file = NULL; 358 FILE *data_file = NULL;
351 data_file = fopen("data","r"); 359 data_file = fopen("data","r");
@@ -360,7 +368,7 @@ void load_key()
360 exit(1); 368 exit(1);
361 } 369 }
362 Messenger_load(data, size); 370 Messenger_load(data, size);
363 } else { 371 } else {
364 //else save new keys 372 //else save new keys
365 int size = Messenger_size(); 373 int size = Messenger_size();
366 uint8_t data[size]; 374 uint8_t data[size];
@@ -395,39 +403,24 @@ int main(int argc, char *argv[])
395 m_callback_friendmessage(print_message); 403 m_callback_friendmessage(print_message);
396 m_callback_namechange(print_nickchange); 404 m_callback_namechange(print_nickchange);
397 m_callback_userstatus(print_statuschange); 405 m_callback_userstatus(print_statuschange);
398 char idstring0[200]; 406
399 char idstring1[PUB_KEY_BYTES][5]; 407 char idstring[200];
400 char idstring2[PUB_KEY_BYTES][5]; 408 get_id(idstring);
401 int i;
402 for(i = 0; i < PUB_KEY_BYTES; i++)
403 {
404 if (self_public_key[i] < (PUB_KEY_BYTES / 2))
405 strcpy(idstring1[i],"0");
406 else
407 strcpy(idstring1[i], "");
408 sprintf(idstring2[i], "%hhX",self_public_key[i]);
409 }
410 strcpy(idstring0,"[i] your ID: ");
411 int j;
412 for (j = 0; j < PUB_KEY_BYTES; j++) {
413 strcat(idstring0,idstring1[j]);
414 strcat(idstring0,idstring2[j]);
415 }
416 initscr(); 409 initscr();
417 noecho(); 410 noecho();
418 raw(); 411 raw();
419 getmaxyx(stdscr, y, x); 412 getmaxyx(stdscr, y, x);
420 new_lines(idstring0); 413 new_lines(idstring);
421 new_lines(help); 414 new_lines(help);
422 strcpy(line, ""); 415 strcpy(line, "");
423 IP_Port bootstrap_ip_port; 416 IP_Port bootstrap_ip_port;
424 bootstrap_ip_port.port = htons(atoi(argv[2])); 417 bootstrap_ip_port.port = htons(atoi(argv[2]));
425 int resolved_address = resolve_addr(argv[1]); 418 int resolved_address = resolve_addr(argv[1]);
426 if (resolved_address != -1) 419 if (resolved_address != 0)
427 bootstrap_ip_port.ip.i = resolved_address; 420 bootstrap_ip_port.ip.i = resolved_address;
428 else 421 else
429 exit(1); 422 exit(1);
430 423
431 DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); 424 DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3]));
432 nodelay(stdscr, TRUE); 425 nodelay(stdscr, TRUE);
433 while(true) { 426 while(true) {
@@ -448,7 +441,7 @@ int main(int argc, char *argv[])
448 if (c == '\n') { 441 if (c == '\n') {
449 line_eval(lines, line); 442 line_eval(lines, line);
450 strcpy(line, ""); 443 strcpy(line, "");
451 } else if (c == 127) { 444 } else if (c == 8 || c == 127) {
452 line[strlen(line)-1] = '\0'; 445 line[strlen(line)-1] = '\0';
453 } else if (isalnum(c) || ispunct(c) || c == ' ') { 446 } else if (isalnum(c) || ispunct(c) || c == ' ') {
454 strcpy(line, appender(line, (char) c)); 447 strcpy(line, appender(line, (char) c));
diff --git a/testing/nTox_win32.c b/testing/nTox_win32.c
index b9208d4f..5501ecf5 100644
--- a/testing/nTox_win32.c
+++ b/testing/nTox_win32.c
@@ -28,9 +28,11 @@
28 28
29uint8_t pending_requests[256][CLIENT_ID_SIZE]; 29uint8_t pending_requests[256][CLIENT_ID_SIZE];
30uint8_t num_requests = 0; 30uint8_t num_requests = 0;
31uint32_t maxnumfriends;
31 32
32char line[STRING_LENGTH]; 33char line[STRING_LENGTH];
33char users_id[200]; 34char users_id[200];
35int friend_request_received;
34 36
35void do_header() 37void do_header()
36{ 38{
@@ -43,10 +45,11 @@ void do_header()
43 45
44void print_request(uint8_t *public_key, uint8_t *data, uint16_t length) 46void print_request(uint8_t *public_key, uint8_t *data, uint16_t length)
45{ 47{
48 friend_request_received = 1;
46 printf("\n\n[i] received friend request with message\n"); 49 printf("\n\n[i] received friend request with message\n");
47 printf((char *)data); 50 printf("'%s'",(char *)data);
48 char numchar[100]; 51 char numchar[100];
49 sprintf(numchar, "\n\n[i] accept request with /a %u\n\n", num_requests); 52 sprintf(numchar, "\n[i] accept request with /a %u\n\n", num_requests);
50 printf(numchar); 53 printf(numchar);
51 memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE); 54 memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE);
52 ++num_requests; 55 ++num_requests;
@@ -105,6 +108,7 @@ void load_key()
105 int size = Messenger_size(); 108 int size = Messenger_size();
106 uint8_t data[size]; 109 uint8_t data[size];
107 Messenger_save(data); 110 Messenger_save(data);
111 fclose(data_file);
108 data_file = fopen("data", "w"); 112 data_file = fopen("data", "w");
109 113
110 if (fwrite(data, sizeof(uint8_t), size, data_file) != size) { 114 if (fwrite(data, sizeof(uint8_t), size, data_file) != size) {
@@ -115,30 +119,188 @@ void load_key()
115 fclose(data_file); 119 fclose(data_file);
116} 120}
117 121
122void add_friend()
123{
124 int i;
125 char temp_id[128];
126
127 for (i = 0; i < 128; i++)
128 temp_id[i] = line[i+3];
129
130 int num = m_addfriend(hex_string_to_bin(temp_id), (uint8_t*)"Install Gentoo", sizeof("Install Gentoo"));
131
132 if (num >= 0) {
133 char numstring[100];
134 sprintf(numstring, "\n[i] Friend request sent. Wait to be accepted. Friend id: %d\n\n", num);
135 printf(numstring);
136 ++maxnumfriends;
137 }
138 else if (num == -1)
139 printf("\n[i] Message is too long.\n\n");
140
141 else if (num == -2)
142 printf("\n[i] Please add a message to your friend request.\n\n");
143
144 else if (num == -3)
145 printf("\n[i] That appears to be your own ID.\n\n");
146
147 else if (num == -4)
148 printf("\n[i] Friend request already sent.\n\n");
149
150 else if (num == -5)
151 printf("\n[i] Undefined error when adding friend\n\n");
152}
153
154void list_friends()
155{
156 int i;
157
158 printf("\n[i] Friend List");
159
160 printf("----- PENDING -----\n\n");
161
162 for (i = 0; i <= maxnumfriends; i++) {
163 char name[MAX_NAME_LENGTH];
164 getname(i, (uint8_t*)name);
165 if (m_friendstatus(i) > 0 && m_friendstatus(i) < 4)
166 printf("[%d] %s\n", i, (uint8_t*)name);
167 }
168
169 printf("\n");
170
171 printf("----- ACTIVE -----\n\n");
172
173 for (i = 0; i <= maxnumfriends; i++) {
174 char name[MAX_NAME_LENGTH];
175 getname(i, (uint8_t*)name);
176
177 if (m_friendstatus(i) == 4)
178 printf("[%d] %s\n", i, (uint8_t*)name);
179 }
180
181 printf("\n");
182}
183
184void delete_friend()
185{
186 size_t len = strlen(line);
187 char numstring[len-3];
188 int i;
189
190 for (i = 0; i < len; i++) {
191 if (line[i+3] != ' ')
192 numstring[i] = line[i+3];
193 }
194
195 int num = atoi(numstring);
196 m_delfriend(num);
197 --maxnumfriends;
198 printf("\n\n");
199}
200
201void message_friend()
202{
203 size_t len = strlen(line);
204 char numstring[len-3];
205 char message[len-3];
206 int i;
207
208 for (i = 0; i < len; i++) {
209
210 if (line[i+3] != ' ')
211 numstring[i] = line[i+3];
212
213 else {
214 int j;
215
216 for (j = (i+1); j < len; j++)
217 message[j-i-1] = line[j+3];
218
219 break;
220 }
221 }
222
223 int num = atoi(numstring);
224
225 if(m_sendmessage(num, (uint8_t*) message, sizeof(message)) != 1)
226 printf("\n[i] could not send message (they may be offline): %s\n", message);
227
228 else
229 printf("\n");
230}
231
232void change_nickname()
233{
234 uint8_t name[MAX_NAME_LENGTH];
235 int i = 0;
236 size_t len = strlen(line);
237
238 for (i = 3; i < len; i++) {
239
240 if (line[i] == 0 || line[i] == '\n')
241 break;
242
243 name[i-3] = line[i];
244 }
245
246 name[i-3] = 0;
247 setname(name, i);
248 char numstring[100];
249 sprintf(numstring, "\n[i] changed nick to %s\n\n", (char*)name);
250 printf(numstring);
251
252 FILE *name_file = NULL;
253 name_file = fopen("namefile.txt", "w");
254 fprintf(name_file, "%s", (char*)name);
255 fclose(name_file);
256}
257
258void change_status(int savetofile)
259{
260 uint8_t status[MAX_USERSTATUS_LENGTH];
261 int i = 0;
262 size_t len = strlen(line);
263
264 for (i = 3; i < len; i++) {
265 if (line[i] == 0 || line[i] == '\n')
266 break;
267
268 status[i-3] = line[i];
269 }
270
271 status[i-3] = 0;
272 m_set_userstatus(status, strlen((char*)status));
273 char numstring[100];
274 sprintf(numstring, "\n[i] changed status to %s\n\n", (char*)status);
275 printf(numstring);
276
277 if (savetofile == 1) {
278 FILE* status_file = NULL;
279 status_file = fopen("statusfile.txt", "w");
280 fprintf(status_file, "%s", (char*)status);
281 fclose(status_file);
282 }
283}
284
285void accept_friend_request()
286{
287 friend_request_received = 0;
288 uint8_t numf = atoi(line + 3);
289 char numchar[100];
290 int num = m_addfriend_norequest(pending_requests[numf]);
291 sprintf(numchar, "\n[i] Added friendnumber: %d\n\n", num);
292 printf(numchar);
293 ++maxnumfriends;
294}
295
118void line_eval(char* line) 296void line_eval(char* line)
119{ 297{
120 if(line[0] == '/') { 298 if(line[0] == '/') {
299
121 char inpt_command = line[1]; 300 char inpt_command = line[1];
122 /* Add friend */ 301
123 if(inpt_command == 'f') { 302 if(inpt_command == 'f') {
124 int i; 303 add_friend();
125 char temp_id[128];
126 for (i = 0; i < 128; i++)
127 temp_id[i] = line[i+3];
128 int num = m_addfriend(hex_string_to_bin(temp_id), (uint8_t*)"Install Gentoo", sizeof("Install Gentoo"));
129 if (num >= 0) {
130 char numstring[100];
131 sprintf(numstring, "\n[i] Friend request sent. Wait to be accepted. Friend id: %d\n\n", num);
132 printf(numstring);
133 }
134 else if (num == -1)
135 printf("\nWrong key size\n\n");
136 else if (num == -2)
137 printf("\nYou can't add yourself\n\n");
138 else if (num == -3)
139 printf("\nYou already have this person added\n\n");
140 else if (num == -4)
141 printf("\nUndefined error when adding friend");
142 } 304 }
143 305
144 else if (inpt_command == 'r') { 306 else if (inpt_command == 'r') {
@@ -147,120 +309,35 @@ void line_eval(char* line)
147 } 309 }
148 310
149 else if (inpt_command == 'l') { 311 else if (inpt_command == 'l') {
150 int activefriends = 0; 312 list_friends();
151 int i;
152
153 for (i = 0; i <= getnumfriends(); i++)
154 {
155 if (m_friendstatus(i) == 4)
156 activefriends++;
157 }
158
159 printf("\n[i] Friend List | Total: %d\n\n", activefriends);
160
161 for (i = 0; i <= getnumfriends(); i++) {
162 char name[MAX_NAME_LENGTH];
163 getname(i, (uint8_t*)name);
164 if (m_friendstatus(i) == 4)
165 printf("[%d] %s\n\n", i, (uint8_t*)name);
166 }
167 } 313 }
168 314
169 else if (inpt_command == 'd') { 315 else if (inpt_command == 'd') {
170 size_t len = strlen(line); 316 delete_friend();
171 char numstring[len-3];
172 int i;
173 for (i = 0; i < len; i++) {
174 if (line[i+3] != ' ') {
175 numstring[i] = line[i+3];
176 }
177 }
178 int num = atoi(numstring);
179 m_delfriend(num);
180 printf("\n\n");
181 } 317 }
182 /* Send message to friend */ 318 /* Send message to friend */
183 else if (inpt_command == 'm') { 319 else if (inpt_command == 'm') {
184 size_t len = strlen(line); 320 message_friend();
185 char numstring[len-3];
186 char message[len-3];
187 int i;
188 for (i = 0; i < len; i++) {
189 if (line[i+3] != ' ') {
190 numstring[i] = line[i+3];
191 } else {
192 int j;
193 for (j = (i+1); j < len; j++)
194 message[j-i-1] = line[j+3];
195 break;
196 }
197 }
198 int num = atoi(numstring);
199 if(m_sendmessage(num, (uint8_t*) message, sizeof(message)) != 1) {
200 printf("\n[i] could not send message (they may be offline): %s\n", message);
201 } else {
202 //simply for aesthetics
203 printf("\n");
204 }
205 } 321 }
206 322
207 else if (inpt_command == 'n') { 323 else if (inpt_command == 'n') {
208 uint8_t name[MAX_NAME_LENGTH]; 324 change_nickname();
209 int i = 0;
210 size_t len = strlen(line);
211 for (i = 3; i < len; i++) {
212 if (line[i] == 0 || line[i] == '\n') break;
213 name[i-3] = line[i];
214 }
215 name[i-3] = 0;
216 setname(name, i);
217 char numstring[100];
218 sprintf(numstring, "\n[i] changed nick to %s\n\n", (char*)name);
219 printf(numstring);
220
221 FILE *name_file = NULL;
222 name_file = fopen("namefile.txt", "w");
223 fprintf(name_file, "%s", (char*)name);
224 fclose(name_file);
225 } 325 }
226 326
227 else if (inpt_command == 's') { 327 else if (inpt_command == 's') {
228 uint8_t status[MAX_USERSTATUS_LENGTH]; 328 change_status(1);
229 int i = 0;
230 size_t len = strlen(line);
231 for (i = 3; i < len; i++) {
232 if (line[i] == 0 || line[i] == '\n') break;
233 status[i-3] = line[i];
234 }
235 status[i-3] = 0;
236 m_set_userstatus(status, strlen((char*)status));
237 char numstring[100];
238 sprintf(numstring, "\n[i] changed status to %s\n\n", (char*)status);
239 printf(numstring);
240
241 FILE* status_file = NULL;
242 status_file = fopen("statusfile.txt", "w");
243 fprintf(status_file, "%s", (char*)status);
244 fclose(status_file);
245 } 329 }
246 330
247 else if (inpt_command == 'a') { 331 else if (inpt_command == 'a') {
248 uint8_t numf = atoi(line + 3); 332 if (friend_request_received == 1)
249 char numchar[100]; 333 accept_friend_request(line);
250 sprintf(numchar, "\n[i] friend request %u accepted\n\n", numf);
251 printf(numchar);
252 int num = m_addfriend_norequest(pending_requests[numf]);
253 sprintf(numchar, "\n[i] added friendnumber %d\n\n", num);
254 printf(numchar);
255 } 334 }
256 /* EXIT */ 335 /* EXIT */
257 else if (inpt_command == 'q') { 336 else if (inpt_command == 'q') {
258 uint8_t status[MAX_USERSTATUS_LENGTH] = "Offline"; 337 strcpy(line, "---Offline");
259 m_set_userstatus(status, strlen((char*)status)); 338 change_status(0);
260 exit(EXIT_SUCCESS); 339 exit(EXIT_SUCCESS);
261 } 340 }
262 } else {
263 //nothing atm
264 } 341 }
265} 342}
266 343
@@ -303,8 +380,8 @@ int main(int argc, char *argv[])
303 setname(name, strlen((char*)name)+1); 380 setname(name, strlen((char*)name)+1);
304 nameloaded = 1; 381 nameloaded = 1;
305 printf("%s\n", name); 382 printf("%s\n", name);
306 } 383 fclose(name_file);
307 fclose(name_file); 384 }
308 385
309 FILE* status_file = NULL; 386 FILE* status_file = NULL;
310 status_file = fopen("statusfile.txt", "r"); 387 status_file = fopen("statusfile.txt", "r");
@@ -316,8 +393,8 @@ int main(int argc, char *argv[])
316 m_set_userstatus(status, strlen((char*)status)+1); 393 m_set_userstatus(status, strlen((char*)status)+1);
317 statusloaded = 1; 394 statusloaded = 1;
318 printf("%s\n", status); 395 printf("%s\n", status);
396 fclose(status_file);
319 } 397 }
320 fclose(status_file);
321 398
322 m_callback_friendrequest(print_request); 399 m_callback_friendrequest(print_request);
323 m_callback_friendmessage(print_message); 400 m_callback_friendmessage(print_message);
@@ -346,7 +423,7 @@ int main(int argc, char *argv[])
346 IP_Port bootstrap_ip_port; 423 IP_Port bootstrap_ip_port;
347 bootstrap_ip_port.port = htons(atoi(argv[2])); 424 bootstrap_ip_port.port = htons(atoi(argv[2]));
348 int resolved_address = resolve_addr(argv[1]); 425 int resolved_address = resolve_addr(argv[1]);
349 if (resolved_address != -1) 426 if (resolved_address != 0)
350 bootstrap_ip_port.ip.i = resolved_address; 427 bootstrap_ip_port.ip.i = resolved_address;
351 else 428 else
352 exit(1); 429 exit(1);
@@ -384,4 +461,4 @@ int main(int argc, char *argv[])
384 Sleep(1); 461 Sleep(1);
385 } 462 }
386 return 0; 463 return 0;
387} \ No newline at end of file 464}
diff --git a/testing/nTox_win32.h b/testing/nTox_win32.h
index 374348a4..271403b8 100644
--- a/testing/nTox_win32.h
+++ b/testing/nTox_win32.h
@@ -34,6 +34,13 @@ void print_message(int friendnumber, uint8_t * string, uint16_t length);
34void print_nickchange(int friendnumber, uint8_t *string, uint16_t length); 34void print_nickchange(int friendnumber, uint8_t *string, uint16_t length);
35void print_statuschange(int friendnumber, uint8_t *string, uint16_t length); 35void print_statuschange(int friendnumber, uint8_t *string, uint16_t length);
36void load_key(); 36void load_key();
37void add_friend();
38void list_friends();
39void delete_friend();
40void message_friend();
41void change_nickname();
42void change_status(int savetofile);
43void accept_friend_request();
37void line_eval(char* line); 44void line_eval(char* line);
38void get_input(); 45void get_input();
39 46
diff --git a/testing/toxic/chat.c b/testing/toxic/chat.c
index dceb1d7b..1bfd94f5 100644
--- a/testing/toxic/chat.c
+++ b/testing/toxic/chat.c
@@ -60,6 +60,8 @@ static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t
60 nick[len-1] = '\0'; 60 nick[len-1] = '\0';
61 fix_name(nick); 61 fix_name(nick);
62 62
63 snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num);
64
63 wattron(ctx->history, COLOR_PAIR(3)); 65 wattron(ctx->history, COLOR_PAIR(3));
64 wprintw(ctx->history, " * Your partner changed nick to '%s'\n", nick); 66 wprintw(ctx->history, " * Your partner changed nick to '%s'\n", nick);
65 wattroff(ctx->history, COLOR_PAIR(3)); 67 wattroff(ctx->history, COLOR_PAIR(3));
@@ -104,6 +106,7 @@ static void chat_onKey(ToxWindow* self, int key) {
104} 106}
105 107
106static void chat_onDraw(ToxWindow* self) { 108static void chat_onDraw(ToxWindow* self) {
109 curs_set(1);
107 int x, y; 110 int x, y;
108 ChatContext* ctx = (ChatContext*) self->x; 111 ChatContext* ctx = (ChatContext*) self->x;
109 112
@@ -115,7 +118,7 @@ static void chat_onDraw(ToxWindow* self) {
115 118
116 wclear(ctx->linewin); 119 wclear(ctx->linewin);
117 mvwhline(ctx->linewin, 0, 0, '_', COLS); 120 mvwhline(ctx->linewin, 0, 0, '_', COLS);
118 mvwprintw(ctx->linewin, 1, 0, "%s\n", ctx->line); 121 mvwprintw(self->window, y-1, 0, "%s\n", ctx->line);
119 122
120 wrefresh(self->window); 123 wrefresh(self->window);
121} 124}
@@ -144,7 +147,11 @@ ToxWindow new_chat(int friendnum) {
144 ret.onNickChange = &chat_onNickChange; 147 ret.onNickChange = &chat_onNickChange;
145 ret.onStatusChange = &chat_onStatusChange; 148 ret.onStatusChange = &chat_onStatusChange;
146 149
147 snprintf(ret.title, sizeof(ret.title), "[chat %d]", friendnum); 150 uint8_t nick[MAX_NAME_LENGTH] = {0};
151 getname(friendnum, (uint8_t*) &nick);
152 fix_name(nick);
153
154 snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum);
148 155
149 ChatContext* x = calloc(1, sizeof(ChatContext)); 156 ChatContext* x = calloc(1, sizeof(ChatContext));
150 x->friendnum = friendnum; 157 x->friendnum = friendnum;
diff --git a/testing/toxic/friendlist.c b/testing/toxic/friendlist.c
index f9a413f9..b4b619a2 100644
--- a/testing/toxic/friendlist.c
+++ b/testing/toxic/friendlist.c
@@ -113,6 +113,7 @@ static void friendlist_onKey(ToxWindow* self, int key) {
113} 113}
114 114
115static void friendlist_onDraw(ToxWindow* self) { 115static void friendlist_onDraw(ToxWindow* self) {
116 curs_set(0);
116 size_t i; 117 size_t i;
117 118
118 wclear(self->window); 119 wclear(self->window);
diff --git a/testing/toxic/main.c b/testing/toxic/main.c
index fffc3f84..391b0b39 100644
--- a/testing/toxic/main.c
+++ b/testing/toxic/main.c
@@ -50,7 +50,7 @@ void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) {
50void on_message(int friendnumber, uint8_t* string, uint16_t length) { 50void on_message(int friendnumber, uint8_t* string, uint16_t length) {
51 size_t i; 51 size_t i;
52 52
53 wprintw(prompt->window, "\n(message) %d: %s!\n", friendnumber, string); 53 wprintw(prompt->window, "\n(message) %d: %s\n", friendnumber, string);
54 54
55 for(i=0; i<w_num; i++) { 55 for(i=0; i<w_num; i++) {
56 if(windows[i].onMessage != NULL) 56 if(windows[i].onMessage != NULL)
@@ -297,14 +297,17 @@ int main(int argc, char* argv[]) {
297 a = &windows[w_active]; 297 a = &windows[w_active];
298 prepare_window(a->window); 298 prepare_window(a->window);
299 a->blink = false; 299 a->blink = false;
300 a->onDraw(a);
301 draw_bar(); 300 draw_bar();
301 a->onDraw(a);
302 302
303 // Handle input. 303 // Handle input.
304 ch = getch(); 304 ch = getch();
305 if(ch == '\t') { 305 if(ch == '\t') {
306 w_active = (w_active + 1) % w_num; 306 w_active = (w_active + 1) % w_num;
307 } 307 }
308 else if(ch == KEY_BTAB) {
309 w_active = (w_active + w_num - 1) % w_num;
310 }
308 else if(ch != ERR) { 311 else if(ch != ERR) {
309 a->onKey(a, ch); 312 a->onKey(a, ch);
310 } 313 }
diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c
index e18bdff0..1db60883 100644
--- a/testing/toxic/prompt.c
+++ b/testing/toxic/prompt.c
@@ -16,6 +16,7 @@ uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX
16uint8_t num_requests=0; // XXX 16uint8_t num_requests=0; // XXX
17 17
18extern void on_friendadded(int friendnumber); 18extern void on_friendadded(int friendnumber);
19static void print_usage(ToxWindow* self);
19 20
20// XXX: 21// XXX:
21int add_req(uint8_t* public_key) { 22int add_req(uint8_t* public_key) {
@@ -82,8 +83,8 @@ static void execute(ToxWindow* self, char* cmd) {
82 83
83 dht.port = htons(atoi(port)); 84 dht.port = htons(atoi(port));
84 85
85 int resolved_address = resolve_addr(ip); 86 uint32_t resolved_address = resolve_addr(ip);
86 if (resolved_address == -1) { 87 if (resolved_address == 0) {
87 return; 88 return;
88 } 89 }
89 90
@@ -133,29 +134,31 @@ static void execute(ToxWindow* self, char* cmd) {
133 } 134 }
134 135
135 num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); 136 num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1);
136 137 switch (num) {
137 wprintw(self->window, "Friend added as %d.\n", num); 138 case -1:
138 on_friendadded(num); 139 wprintw(self->window, "Message is too long.\n");
140 break;
141 case -2:
142 wprintw(self->window, "Please add a message to your request.\n");
143 break;
144 case -3:
145 wprintw(self->window, "That appears to be your own ID.\n");
146 break;
147 case -4:
148 wprintw(self->window, "Friend request already sent.\n");
149 break;
150 case -5:
151 wprintw(self->window, "[i] Undefined error when adding friend.\n");
152 break;
153 default:
154 wprintw(self->window, "Friend added as %d.\n", num);
155 on_friendadded(num);
156 break;
157 }
139 } 158 }
140 else if(!strcmp(cmd, "help")) {
141 wattron(self->window, COLOR_PAIR(2) | A_BOLD);
142 wprintw(self->window, "Commands:\n");
143 wattroff(self->window, A_BOLD);
144
145 wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n");
146 wprintw(self->window, " add <id> <message> : Add friend\n");
147 wprintw(self->window, " status <message> : Set your status\n");
148 wprintw(self->window, " nick <nickname> : Set your nickname\n");
149 wprintw(self->window, " accept <number> : Accept friend request\n");
150 wprintw(self->window, " myid : Print your ID\n");
151 wprintw(self->window, " quit/exit : Exit program\n");
152
153 159
154 wattron(self->window, A_BOLD); 160 else if(!strcmp(cmd, "help")) {
155 wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); 161 print_usage(self);
156 wattroff(self->window, A_BOLD);
157
158 wattroff(self->window, COLOR_PAIR(2));
159 } 162 }
160 else if(!strncmp(cmd, "status ", strlen("status "))) { 163 else if(!strncmp(cmd, "status ", strlen("status "))) {
161 char* msg; 164 char* msg;
@@ -285,6 +288,7 @@ static void prompt_onKey(ToxWindow* self, int key) {
285} 288}
286 289
287static void prompt_onDraw(ToxWindow* self) { 290static void prompt_onDraw(ToxWindow* self) {
291 curs_set(1);
288 int x, y; 292 int x, y;
289 293
290 getyx(self->window, y, x); 294 getyx(self->window, y, x);