diff options
39 files changed, 2285 insertions, 1087 deletions
@@ -3,6 +3,7 @@ | |||
3 | //nacl build | 3 | //nacl build |
4 | nacl/build/ | 4 | nacl/build/ |
5 | build | 5 | build |
6 | sodium | ||
6 | 7 | ||
7 | CMakeCache.txt | 8 | CMakeCache.txt |
8 | CMakeFiles | 9 | CMakeFiles |
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 | ||
26 | script: | 27 | script: |
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 | ||
31 | notifications: | 34 | notifications: |
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 | ||
3 | set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) | 3 | set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) |
4 | 4 | ||
5 | if(UNIX) | ||
6 | find_package(Curses REQUIRED) | ||
7 | endif() | ||
8 | |||
5 | if(NOT WIN32) | 9 | if(NOT WIN32) |
6 | option(USE_NACL "Use NaCl library instead of libsodium") | 10 | option(USE_NACL "Use NaCl library instead of libsodium") |
7 | endif() | 11 | endif() |
@@ -29,15 +33,15 @@ if(NOT USE_NACL) | |||
29 | endif() | 33 | endif() |
30 | 34 | ||
31 | macro(linkCoreLibraries exe_name) | 35 | macro(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) | |||
48 | add_subdirectory(core) | 52 | add_subdirectory(core) |
49 | add_subdirectory(testing) | 53 | add_subdirectory(testing) |
50 | add_subdirectory(other) | 54 | add_subdirectory(other) |
55 | add_subdirectory(docs) | ||
@@ -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 |
20 | apt-get install build-essential libtool autotools-dev automake libconfig-dev ncurses-dev cmake checkinstall | 19 | apt-get install build-essential libtool autotools-dev automake libconfig-dev ncurses-dev cmake checkinstall |
21 | ``` | 20 | ``` |
21 | |||
22 | On Fedora: | ||
23 | |||
24 | ```bash | ||
25 | yum groupinstall "Development Tools" | ||
26 | yum install libtool autoconf automake libconfig-devel ncurses-devel cmake | ||
27 | ``` | ||
28 | |||
22 | Note that `libconfig-dev` should be >= 1.4. | 29 | Note that `libconfig-dev` should be >= 1.4. |
23 | 30 | ||
24 | You should get and install [libsodium](https://github.com/jedisct1/libsodium): | 31 | You should get and install [libsodium](https://github.com/jedisct1/libsodium): |
@@ -32,11 +39,28 @@ sudo checkinstall --install --pkgname libsodium --pkgversion 0.4.2 --nodoc | |||
32 | sudo ldconfig | 39 | sudo ldconfig |
33 | ``` | 40 | ``` |
34 | 41 | ||
35 | Then clone this repo and run: | 42 | Or if checkinstall is not easily available for your distribution (e.g. Fedora), |
43 | this will install the libs to /usr/local/lib and the headers to /usr/local/include: | ||
44 | |||
36 | ```bash | 45 | ```bash |
46 | git clone git://github.com/jedisct1/libsodium.git | ||
47 | cd libsodium | ||
48 | git checkout tags/0.4.2 | ||
49 | ./autogen.sh | ||
50 | ./configure | ||
51 | make check | ||
52 | sudo make install | ||
53 | ``` | ||
54 | |||
55 | |||
56 | Then clone this repo and generate makefile: | ||
57 | ```bash | ||
58 | git clone git://github.com/irungentoo/ProjectTox-Core.git | ||
59 | cd ProjectTox-Core | ||
37 | mkdir build && cd build | 60 | mkdir build && cd build |
38 | cmake .. | 61 | cmake .. |
39 | ``` | 62 | ``` |
63 | Note that you should call cmake on the root [`CMakeLists.txt`](/CMakeLists.txt) file only. | ||
40 | 64 | ||
41 | Then you can build any of the [`/testing`](/testing) and [`/other`](/other) that are currently supported on your platform by running: | 65 | Then 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 | ||
82 | You need the latest XCode with the Developer Tools (Preferences -> Downloads -> Command Line Tools). | ||
83 | The 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 | |||
85 | There 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 | ``` |
61 | brew install libtool automake autoconf libconfig libsodium | 90 | brew install libtool automake autoconf libconfig libsodium cmake |
62 | cmake . | 91 | cmake . |
63 | make | 92 | make |
64 | sudo make install | ||
65 | ``` | 93 | ``` |
66 | 94 | ||
67 | <a name="non-homebrew" /> | 95 | <a name="non-homebrew" /> |
68 | ####Non-homebrew: | 96 | ####Non-homebrew: |
69 | 97 | ||
70 | Much the same as Linux, remember to install the latest XCode and the developer tools (Preferences -> Downloads -> Command Line Tools). | 98 | Grab the following packages: |
71 | Users 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/ |
72 | They 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 | |||
105 | Uncompress 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 | |||
77 | sudo make install | 110 | sudo make install |
78 | ``` | 111 | ``` |
79 | 112 | ||
113 | In your local TOX repository: | ||
114 | |||
115 | ```bash | ||
116 | cmake . | ||
117 | make | ||
118 | ``` | ||
119 | |||
80 | Do not install them from macports (or any dependencies for that matter) as they get shoved in the wrong directory | 120 | Do not install them from macports (or any dependencies for that matter) as they get shoved in the wrong directory |
81 | and make your life more annoying. | 121 | and make your life more annoying. |
82 | 122 | ||
@@ -102,6 +142,7 @@ Navigate in `cmd` to this repo and run: | |||
102 | mkdir build && cd build | 142 | mkdir build && cd build |
103 | cmake -G "MinGW Makefiles" .. | 143 | cmake -G "MinGW Makefiles" .. |
104 | ``` | 144 | ``` |
145 | Note that you should call cmake on the root [`CMakeLists.txt`](/CMakeLists.txt) file only. | ||
105 | 146 | ||
106 | Then you can build any of the [`/testing`](/testing) and [`/other`](/other) that are currently supported on your platform by running: | 147 | Then 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 | |||
117 | mingw32-make | 158 | mingw32-make |
118 | ``` | 159 | ``` |
119 | 160 | ||
120 | <a name="usage" /> | ||
121 | ## Usage | ||
122 | |||
123 | - [Start Guide](start_guide.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 | ||
37 | For further information, check our [To-do list](https://github.com/irungentoo/ProjectTox-Core/wiki/TODO) | 39 | For 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. |
40 | The goal of this project is to create a configuration-free P2P skype | 42 | The goal of this project is to create a configuration-free P2P skype |
41 | replacement. Configuration-free means that the user will simply have to open the program and | 43 | replacement. Configuration-free means that the user will simply have to open the program and |
42 | without any account configuration will be capable of adding people to his | 44 | without any account configuration will be capable of adding people to his |
43 | friends list and start conversing with them. There are many so called skype replacements and all of them are either hard to | 45 | friends list and start conversing with them. There are many so-called skype replacements and all of them are either hard to |
44 | configure for the normal user or suffer from being way too centralized. | 46 | configure 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 | |||
24 | set(_SODIUM_ROOT_HINTS | ||
25 | ) | ||
26 | |||
27 | set(_SODIUM_ROOT_PATHS | ||
28 | "$ENV{PROGRAMFILES}/sodium" | ||
29 | ) | ||
30 | |||
31 | find_path(SODIUM_ROOT_DIR | ||
32 | NAMES | ||
33 | include/cmocka.h | ||
34 | HINTS | ||
35 | ${_SODIUM_ROOT_HINTS} | ||
36 | PATHS | ||
37 | ${_SODIUM_ROOT_PATHS} | ||
38 | ) | ||
39 | mark_as_advanced(SODIUM_ROOT_DIR) | ||
40 | |||
41 | find_path(SODIUM_INCLUDE_DIR | ||
42 | NAMES | ||
43 | sodium.h | ||
44 | PATHS | ||
45 | ${SODIUM_ROOT_DIR}/include | ||
46 | ) | ||
47 | |||
48 | find_library(SODIUM_LIBRARY | ||
49 | NAMES | ||
50 | sodium | ||
51 | PATHS | ||
52 | ${SODIUM_ROOT_DIR}/lib | ||
53 | ) | ||
7 | 54 | ||
8 | FIND_PATH(SODIUM_INCLUDE_DIR NAMES sodium.h) | 55 | if (SODIUM_LIBRARY) |
56 | set(SODIUM_LIBRARIES | ||
57 | ${SODIUM_LIBRARIES} | ||
58 | ${SODIUM_LIBRARY} | ||
59 | ) | ||
60 | endif (SODIUM_LIBRARY) | ||
9 | 61 | ||
10 | FIND_LIBRARY(SODIUM_LIBRARY NAMES sodium) | 62 | include(FindPackageHandleStandardArgs) |
63 | find_package_handle_standard_args(SODIUM DEFAULT_MSG SODIUM_LIBRARIES SODIUM_INCLUDE_DIR) | ||
11 | 64 | ||
12 | INCLUDE(FindPackageHandleStandardArgs) | 65 | # show the SODIUM_INCLUDE_DIR and SODIUM_LIBRARIES variables only in the advanced view |
13 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(SODIUM DEFAULT_MSG SODIUM_LIBRARY SODIUM_INCLUDE_DIR) | 66 | mark_as_advanced(SODIUM_INCLUDE_DIR SODIUM_LIBRARIES) |
14 | 67 | ||
15 | MARK_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 @@ | |||
1 | find_program(SPHINX_EXECUTABLE NAMES sphinx-build | ||
2 | HINTS | ||
3 | $ENV{SPHINX_DIR} | ||
4 | PATH_SUFFIXES bin | ||
5 | DOC "Sphinx documentation generator" | ||
6 | ) | ||
7 | |||
8 | include(FindPackageHandleStandardArgs) | ||
9 | |||
10 | find_package_handle_standard_args(Sphinx DEFAULT_MSG | ||
11 | SPHINX_EXECUTABLE | ||
12 | ) | ||
13 | |||
14 | mark_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 @@ | |||
1 | cmake_minimum_required(VERSION 2.6.0) | 1 | cmake_minimum_required(VERSION 2.6.0) |
2 | project(core C) | 2 | project(toxcore C) |
3 | 3 | ||
4 | if(WIN32) | 4 | if(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 | ||
19 | add_library(core ${core_sources}) | 19 | add_library(toxcore SHARED ${core_sources}) |
@@ -21,102 +21,156 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "DHT.h" | 24 | /*----------------------------------------------------------------------------------*/ |
25 | 25 | ||
26 | typedef 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 | ||
39 | typedef 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 | ||
53 | typedef struct { | 64 | typedef 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 | ||
58 | typedef struct { | 75 | typedef 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 */ |
66 | uint8_t self_public_key[CLIENT_ID_SIZE]; | ||
67 | uint8_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; |
72 | static 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 | ||
74 | static Friend * friends_list; | 93 | typedef struct { |
75 | static 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 */ | 98 | typedef struct { |
78 | #define LPING_ARRAY 256 | 99 | IP_Port ip_port; |
100 | uint64_t ping_id; | ||
101 | uint64_t timestamp; | ||
102 | } Pinged; | ||
79 | 103 | ||
80 | static Pinged pings[LPING_ARRAY]; | 104 | /*----------------------------------------------------------------------------------*/ |
81 | 105 | ||
82 | #define LSEND_NODES_ARRAY LPING_ARRAY/2 | 106 | /* Our client id/public key */ |
107 | uint8_t self_public_key[CLIENT_ID_SIZE]; | ||
108 | uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; | ||
109 | static Client_data close_clientlist[LCLIENT_LIST]; | ||
110 | static Friend * friends_list; | ||
111 | static uint16_t num_friends; | ||
112 | static Pinged pings[LPING_ARRAY]; | ||
113 | static Pinged send_nodes[LSEND_NODES_ARRAY]; | ||
83 | 114 | ||
84 | static 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 |
90 | int id_closest(uint8_t * client_id, uint8_t * client_id1, uint8_t * client_id2) /* tested */ | 121 | */ |
122 | int 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 | ||
140 | int ipport_equal(IP_Port a, IP_Port b) | ||
141 | { | ||
142 | return (a.ip.i == b.ip.i) && (a.port == b.port); | ||
143 | } | ||
144 | |||
145 | int id_equal(uint8_t* a, uint8_t* b) | ||
146 | { | ||
147 | return memcmp(a, b, CLIENT_ID_SIZE) == 0; | ||
148 | } | ||
149 | |||
150 | int 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 | */ | ||
107 | int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port) | 162 | int 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 | */ | ||
133 | int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id) | 187 | int 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 | */ |
144 | static int friend_number(uint8_t * client_id) | 201 | static 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 | */ | ||
161 | int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) | 218 | int 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) |
204 | int replace_bad(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port) /* tested */ | 303 | */ |
304 | int 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 */ |
223 | int replace_good(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port, uint8_t * comp_client_id) | 328 | int 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 | */ | ||
243 | void addto_lists(IP_Port ip_port, uint8_t * client_id) | 354 | void 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 | */ | ||
262 | void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient_id) | 396 | void 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 |
291 | TODO: optimize this */ | 433 | */ |
292 | int is_pinging(IP_Port ip_port, uint64_t ping_id) | 434 | int 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 | */ | ||
344 | uint64_t add_pinging(IP_Port ip_port) | 489 | uint64_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 | */ | ||
383 | static int pingreq(IP_Port ip_port, uint8_t * public_key) | 533 | static 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) | |||
412 | static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id) | 567 | static 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) | |||
435 | static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) | 596 | static 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 */ |
470 | static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, uint64_t ping_id) | 635 | static 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 | */ |
509 | int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source) | 679 | int 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 | ||
553 | int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source) | 732 | int 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 | ||
580 | int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source) | 764 | int 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 | ||
624 | int DHT_addfriend(uint8_t * client_id) | 809 | int 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) | |||
659 | IP_Port DHT_getfriendip(uint8_t * client_id) | 853 | IP_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. */ | ||
690 | void doDHTFriends() | 876 | void 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 | ||
720 | static uint32_t close_lastgetnodes; | 910 | static 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. |
724 | void doClose() /* tested */ | 914 | */ |
915 | void 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 | */ | ||
762 | int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length) | 956 | int 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 | */ | ||
776 | static int friend_iplist(IP_Port * ip_portlist, uint16_t friend_num) | 974 | static 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 | */ | ||
797 | int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) | 1005 | int 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 | */ | ||
818 | int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) | 1032 | int 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 | */ | ||
847 | int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id) | 1068 | int 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 | ||
860 | int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) | 1082 | int 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 */ |
883 | int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source) | 1108 | int 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 | */ | ||
924 | static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num) | 1158 | static 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 | */ | ||
946 | static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip) | 1183 | static 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 | |||
960 | static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t friend_num) | 1197 | static 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 | |||
978 | static void doNAT() | 1214 | static 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 | ||
1013 | int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) | 1252 | int 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 | */ | ||
1062 | int DHT_load(uint8_t * data, uint32_t size) | 1302 | int 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 | */ | ||
1096 | int DHT_isconnected() | 1344 | int 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 | } |
@@ -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 */ | ||
32 | uint32_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 */ | ||
29 | IP broadcast_ip() | 79 | IP 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 |
32 | extern "C" { | 39 | extern "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 */ |
38 | timeout 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 | ||
47 | typedef struct { | 46 | typedef 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 | ||
52 | typedef struct { | 51 | typedef 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 | */ | ||
100 | int getconnection_id(IP_Port ip_port) | 130 | int 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. */ |
112 | static uint32_t randtable[6][256]; | 144 | static 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 | */ | ||
117 | uint32_t handshake_id(IP_Port source) | 152 | uint32_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 | */ | ||
132 | void change_handshake(IP_Port source) | 171 | void 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 | */ | ||
142 | int new_connection(IP_Port ip_port) | 183 | int 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 | */ | ||
187 | int new_inconnection(IP_Port ip_port) | 237 | int 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 | */ | ||
227 | int incoming_connection() | 287 | int 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. */ | ||
239 | static void free_connections() | 301 | static 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 | */ | ||
258 | int kill_connection(int connection_id) | 324 | int 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 | */ | ||
275 | int kill_connection_in(int connection_id, uint32_t seconds) | 343 | int 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 | */ | ||
292 | int is_connected(int connection_id) | 362 | int 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 | */ | ||
352 | int write_packet(int connection_id, uint8_t * data, uint32_t length) | 426 | int 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 | |||
391 | int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) | 473 | int 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 | ||
404 | int send_SYNC(uint32_t connection_id) | 487 | int 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. */ | ||
470 | int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source) | 558 | int 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. */ | ||
503 | int SYNC_valid(uint32_t length) | 594 | int 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: */ |
514 | int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) | 605 | int 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: */ |
534 | int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) | 625 | int 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: */ |
547 | int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum, uint32_t * req_packets, | 638 | int 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 | */ | ||
603 | int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) | 711 | int 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 | ||
654 | int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source) | 773 | int 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 | */ | ||
675 | void doNew() | 796 | void 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 | */ | ||
728 | void adjustRates() | 854 | void 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. */ | ||
749 | void doLossless_UDP() | 874 | void 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 | */ |
42 | int new_connection(IP_Port ip_port); | 42 | int 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 | */ | ||
47 | int getconnection_id(IP_Port ip_port); | 49 | int 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 | */ | ||
51 | int incoming_connection(); | 55 | int 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 | */ | ||
55 | int kill_connection(int connection_id); | 61 | int 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 | */ | ||
60 | int kill_connection_in(int connection_id, uint32_t seconds); | 68 | int 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 | */ | ||
64 | IP_Port connection_ip(int connection_id); | 74 | IP_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 | */ | ||
68 | char id_packet(int connection_id); | 80 | char 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 | */ | ||
72 | int read_packet(int connection_id, uint8_t *data); | 86 | int 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 | */ | ||
76 | int write_packet(int connection_id, uint8_t *data, uint32_t length); | 92 | int 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. */ |
79 | uint32_t sendqueue(int connection_id); | 95 | uint32_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 | */ | ||
82 | uint32_t recvqueue(int connection_id); | 101 | uint32_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 | */ | ||
90 | int is_connected(int connection_id); | 110 | int 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. */ | ||
94 | void doLossless_UDP(); | 113 | void 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 | */ | ||
100 | int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source); | 120 | int 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 @@ | |||
27 | typedef struct { | 27 | typedef 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 */ | ||
75 | int 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 | */ | ||
106 | int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) | 103 | int 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 | ||
135 | int m_addfriend_norequest(uint8_t * client_id) | 136 | int 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 */ |
184 | int m_friendstatus(int friendnumber) | 185 | int 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 | ||
487 | static uint32_t last_LANdiscovery; | 488 | static 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*/ |
490 | static void LANdiscovery() | 491 | static 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 | */ | ||
57 | int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length); | 75 | int 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 | ||
49 | static Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS]; | 49 | static 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]; | |||
60 | int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | 66 | int 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 |
172 | int resolve_addr(const char *address) | 172 | returns 0 on failure |
173 | |||
174 | TODO: Fix ipv6 support | ||
175 | */ | ||
176 | uint32_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) */ |
117 | void shutdown_networking(); | 118 | void 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 |
124 | int resolve_addr(const char *address); | 125 | returns 0 on failure |
126 | |||
127 | TODO: Fix ipv6 support | ||
128 | */ | ||
129 | uint32_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 | ||
2 | find_package(Sphinx) | ||
3 | |||
4 | if(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") | ||
35 | else() | ||
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") | ||
40 | endif() | ||
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 | ||
2 | Here's a list of commands that nTox accepts, | ||
3 | which can all be used by starting your line with | ||
4 | a */*. 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 @@ | |||
1 | Tox User Commands | ||
2 | ================= | ||
3 | |||
4 | Here's a list of commands that nTox accepts, which can all be used by | ||
5 | starting your line with a */*. Currently there can be no spaces before | ||
6 | this. | ||
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 | |||
14 | import 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. | ||
28 | extensions = [] | ||
29 | |||
30 | # Add any paths that contain templates here, relative to this directory. | ||
31 | templates_path = ['_templates'] | ||
32 | |||
33 | # The suffix of source filenames. | ||
34 | source_suffix = '.rst' | ||
35 | |||
36 | # The encoding of source files. | ||
37 | #source_encoding = 'utf-8-sig' | ||
38 | |||
39 | # The master toctree document. | ||
40 | master_doc = 'index' | ||
41 | |||
42 | # General information about the project. | ||
43 | project = u'ProjectTox' | ||
44 | copyright = 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. | ||
51 | version = '0.1' | ||
52 | # The full version, including alpha/beta/rc tags. | ||
53 | release = '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. | ||
67 | exclude_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. | ||
84 | pygments_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. | ||
94 | html_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". | ||
123 | html_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. | ||
167 | htmlhelp_basename = 'ProjectToxdoc' | ||
168 | |||
169 | |||
170 | # -- Options for LaTeX output -------------------------------------------------- | ||
171 | |||
172 | latex_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]). | ||
185 | latex_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). | ||
215 | man_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) | ||
229 | texinfo_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 | |||
6 | Welcome to ProjectTox's documentation! | ||
7 | ====================================== | ||
8 | |||
9 | Contents: | ||
10 | |||
11 | .. toctree:: | ||
12 | start_guide.rst | ||
13 | install.rst | ||
14 | commands.rst | ||
15 | :maxdepth: 2 | ||
16 | |||
17 | |||
18 | |||
19 | Indices 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 @@ | |||
1 | Install Instructions | ||
2 | ==================== | ||
3 | |||
4 | Linux | ||
5 | --------- | ||
6 | |||
7 | First, 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 | |||
14 | Then 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 | |||
24 | Finally, 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 | |||
30 | Then you can build any of the files in `/testing`_ and `/other`_ that are currently | ||
31 | supported on your platform by running :: | ||
32 | |||
33 | make name_of_c_file | ||
34 | |||
35 | For example, to build `Messenger_test.c`_ you would run :: | ||
36 | |||
37 | make Messenger_test | ||
38 | |||
39 | |||
40 | Or you could just build everything that is supported on your platform by | ||
41 | running :: | ||
42 | bash make | ||
43 | |||
44 | OS X | ||
45 | ------ | ||
46 | |||
47 | Homebrew | ||
48 | ~~~~~~~~~~ | ||
49 | :: | ||
50 | |||
51 | brew install libtool automake autoconf libconfig libsodium cmake | ||
52 | cmake . | ||
53 | make | ||
54 | sudo make install | ||
55 | |||
56 | Non-homebrew | ||
57 | ~~~~~~~~~~~~ | ||
58 | |||
59 | Much the same as Linux, remember to install the latest XCode and the | ||
60 | developer tools (Preferences -> Downloads -> Command Line Tools). Users | ||
61 | running Mountain Lion and the latest version of XCode (4.6.3) will also | ||
62 | need to install libtool, automake and autoconf. They are easy enough to | ||
63 | install, grab them from http://www.gnu.org/software/libtool/, | ||
64 | http://www.gnu.org/software/autoconf/ and | ||
65 | http://www.gnu.org/software/automake/, then follow these steps for each: | ||
66 | |||
67 | :: | ||
68 | |||
69 | ./configure | ||
70 | make | ||
71 | sudo make install | ||
72 | |||
73 | Do not install them from macports (or any dependencies for that matter) | ||
74 | as they get shoved in the wrong directory and make your life more | ||
75 | annoying. | ||
76 | |||
77 | Another thing you may want to install is the latest gcc, this caused me | ||
78 | a few problems as XCode from 4.3 no longer includes gcc and instead uses | ||
79 | LLVM-GCC, a nice install guide can be found at | ||
80 | http://caiustheory.com/install-gcc-421-apple-build-56663-with-xcode-42 | ||
81 | |||
82 | Windows | ||
83 | --------- | ||
84 | |||
85 | You should install: | ||
86 | |||
87 | * `MinGW <http://sourceforge.net/projects/mingw/>`_'s C compiler | ||
88 | * `CMake <http://www.cmake.org/cmake/resources/software.html>`_ | ||
89 | |||
90 | You have to `modify your PATH environment | ||
91 | variable <http://www.computerhope.com/issues/ch000549.htm>`_ so that it | ||
92 | contains MinGW's bin folder path. With default settings, the bin folder | ||
93 | is located at ``C:\MinGW\bin``, which means that you would have to | ||
94 | append ``;C:\MinGW\bin`` to the PATH variable. | ||
95 | |||
96 | Then you should either clone this repo by using git, or just download a | ||
97 | `zip of current Master | ||
98 | branch <https://github.com/irungentoo/ProjectTox-Core/archive/master.zip>`_ | ||
99 | and extract it somewhere. | ||
100 | |||
101 | After that you should get precompiled package of libsodium from | ||
102 | `here <https://download.libsodium.org/libsodium/releases/libsodium-win32-0.4.2.tar.gz>`_ | ||
103 | and extract the archive into this repo's root. That is, ``sodium`` | ||
104 | folder should be along with ``core``, ``testing`` and other folders. | ||
105 | |||
106 | Navigate in ``cmd`` to this repo and run:: | ||
107 | |||
108 | mkdir build && cd build | ||
109 | cmake -G "MinGW Makefiles" .. | ||
110 | |||
111 | Then you can build any of the `/testing`_ and `/other`_ that are currently | ||
112 | supported on your platform by running:: | ||
113 | |||
114 | mingw32-make name_of_c_file | ||
115 | |||
116 | For example, to build `Messenger_test.c`_ you would run:: | ||
117 | |||
118 | mingw32-make Messenger_test`` | ||
119 | |||
120 | Or you could just build everything that is supported on your platform by | ||
121 | running:: | ||
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 @@ | |||
1 | Tox nutzen | ||
2 | ========== | ||
3 | |||
4 | 1. :doc:`Tox erstellen <install>` | ||
5 | 2. Fehler korrigieren | ||
6 | 3. Im IRC nach Hilfe fragen | ||
7 | 4. Auf Debug-Reise für Entwickler | ||
8 | 5. Tox wirklich erstellen | ||
9 | 6. ??? | ||
10 | |||
11 | Trotz der ganzen Arbeit, die wir bisher in Tox gesteckt haben, gibt es | ||
12 | noch keine richtige Anleitung, wie man Tox *benutzt*. Dies ist ein | ||
13 | anwenderfreundlicher Versuch. | ||
14 | |||
15 | 1. 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 | |||
31 | 2. 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 | |||
43 | 3. Chatte drauf los! | ||
44 | |||
45 | - Benutze nun den */m*-Befehl, um eine Nachricht an jemanden zu | ||
46 | senden. Wow, du chattest! | ||
47 | |||
48 | 4. 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 | |||
55 | 5. 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 | |||
61 | 6. 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 @@ | |||
1 | Using Tox | ||
2 | ========= | ||
3 | |||
4 | .. note:: There is a German version of this page available: :doc:`start_guide.de` | ||
5 | |||
6 | |||
7 | 1. :doc:`Build Tox <install>` | ||
8 | 2. Fix errors | ||
9 | 3. Consult IRC for help | ||
10 | 4. Go on debugging journey for devs | ||
11 | 5. Build Tox for real | ||
12 | 6. ??? | ||
13 | |||
14 | For all the work we've put into Tox so far, there isn't yet a decent | ||
15 | guide for how you *use* Tox. Here's a user-friendly attempt at it. | ||
16 | |||
17 | 1. 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 | |||
29 | 2. 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 | |||
39 | 3. Chat it up! | ||
40 | |||
41 | - Now use the ``/m`` command to send a message to someone. Wow, | ||
42 | you're chatting! | ||
43 | |||
44 | 4. 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 | |||
51 | 5. 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 | |||
56 | 6. 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 | ||
2 | 1. Build Tox | ||
3 | 2. Fix errors | ||
4 | 3. Consult IRC for help | ||
5 | 4. Go on debugging journy for devs | ||
6 | 5. Build Tox for real | ||
7 | 6. ??? | ||
8 | |||
9 | For all the work we've put into Tox so far, | ||
10 | there isn't yet a decent guide for how you _use_ | ||
11 | Tox. Here's a user-friendly attempt at it. | ||
12 | |||
13 | 1. 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 | ||
21 | 2. 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. | ||
28 | 3. Chat it up! | ||
29 | + Now use the */m* command to send a message to someone. Wow, you're chatting! | ||
30 | 4. 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. | ||
33 | 5. 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. | ||
36 | 6. 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 | ||
2 | 1. Tox erstellen | ||
3 | 2. Fehler korrigieren | ||
4 | 3. Im IRC nach Hilfe fragen | ||
5 | 4. Auf Debug-Reise für Entwickler | ||
6 | 5. Tox wirklich erstellen | ||
7 | 6. ??? | ||
8 | |||
9 | Trotz der ganzen Arbeit, die wir bisher in Tox | ||
10 | gesteckt haben, gibt es noch keine richtige | ||
11 | Anleitung, wie man Tox _benutzt_. | ||
12 | Dies ist ein anwenderfreundlicher Versuch. | ||
13 | |||
14 | 1. 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 | ||
22 | 2. 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. | ||
30 | 3. Chatte drauf los! | ||
31 | + Benutze nun den */m*-Befehl, um eine Nachricht an jemanden zu senden. Wow, du chattest! | ||
32 | 4. 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. | ||
35 | 5. 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. | ||
38 | 6. 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 | ||
2 | 1. [Build Tox](/INSTALL.md) | ||
3 | 2. Fix errors | ||
4 | 3. Consult IRC for help | ||
5 | 4. Go on debugging journy for devs | ||
6 | 5. Build Tox for real | ||
7 | 6. ??? | ||
8 | |||
9 | For all the work we've put into Tox so far, | ||
10 | there isn't yet a decent guide for how you _use_ | ||
11 | Tox. Here's a user-friendly attempt at it. | ||
12 | |||
13 | 1. 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` | ||
21 | 2. 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. | ||
28 | 3. Chat it up! | ||
29 | + Now use the `/m` command to send a message to someone. Wow, you're chatting! | ||
30 | 4. 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. | ||
33 | 5. 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. | ||
36 | 6. 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; | |||
44 | uint8_t pending_requests[256][CLIENT_ID_SIZE]; | 44 | uint8_t pending_requests[256][CLIENT_ID_SIZE]; |
45 | uint8_t num_requests = 0; | 45 | uint8_t num_requests = 0; |
46 | 46 | ||
47 | void 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 | |||
47 | void new_lines(char *line) | 71 | void 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 | ||
314 | void print_message(int friendnumber, uint8_t * string, uint16_t length) | 333 | void 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 | ||
330 | void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) | 338 | void 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 | ||
339 | void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) | 347 | void 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 | ||
348 | void load_key() | 356 | void 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 | ||
29 | uint8_t pending_requests[256][CLIENT_ID_SIZE]; | 29 | uint8_t pending_requests[256][CLIENT_ID_SIZE]; |
30 | uint8_t num_requests = 0; | 30 | uint8_t num_requests = 0; |
31 | uint32_t maxnumfriends; | ||
31 | 32 | ||
32 | char line[STRING_LENGTH]; | 33 | char line[STRING_LENGTH]; |
33 | char users_id[200]; | 34 | char users_id[200]; |
35 | int friend_request_received; | ||
34 | 36 | ||
35 | void do_header() | 37 | void do_header() |
36 | { | 38 | { |
@@ -43,10 +45,11 @@ void do_header() | |||
43 | 45 | ||
44 | void print_request(uint8_t *public_key, uint8_t *data, uint16_t length) | 46 | void 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 | ||
122 | void 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 | |||
154 | void 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 | |||
184 | void 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 | |||
201 | void 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 | |||
232 | void 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 | |||
258 | void 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 | |||
285 | void 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 | |||
118 | void line_eval(char* line) | 296 | void 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); | |||
34 | void print_nickchange(int friendnumber, uint8_t *string, uint16_t length); | 34 | void print_nickchange(int friendnumber, uint8_t *string, uint16_t length); |
35 | void print_statuschange(int friendnumber, uint8_t *string, uint16_t length); | 35 | void print_statuschange(int friendnumber, uint8_t *string, uint16_t length); |
36 | void load_key(); | 36 | void load_key(); |
37 | void add_friend(); | ||
38 | void list_friends(); | ||
39 | void delete_friend(); | ||
40 | void message_friend(); | ||
41 | void change_nickname(); | ||
42 | void change_status(int savetofile); | ||
43 | void accept_friend_request(); | ||
37 | void line_eval(char* line); | 44 | void line_eval(char* line); |
38 | void get_input(); | 45 | void 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 | ||
106 | static void chat_onDraw(ToxWindow* self) { | 108 | static 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 | ||
115 | static void friendlist_onDraw(ToxWindow* self) { | 115 | static 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) { | |||
50 | void on_message(int friendnumber, uint8_t* string, uint16_t length) { | 50 | void 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 | |||
16 | uint8_t num_requests=0; // XXX | 16 | uint8_t num_requests=0; // XXX |
17 | 17 | ||
18 | extern void on_friendadded(int friendnumber); | 18 | extern void on_friendadded(int friendnumber); |
19 | static void print_usage(ToxWindow* self); | ||
19 | 20 | ||
20 | // XXX: | 21 | // XXX: |
21 | int add_req(uint8_t* public_key) { | 22 | int 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 | ||
287 | static void prompt_onDraw(ToxWindow* self) { | 290 | static 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); |