diff options
-rw-r--r-- | .gitignore | 8 | ||||
-rw-r--r-- | .travis.yml | 13 | ||||
-rw-r--r-- | INSTALL.md | 12 | ||||
-rw-r--r-- | README.md | 9 | ||||
-rw-r--r-- | core/Lossless_UDP.c | 6 | ||||
-rw-r--r-- | core/Messenger.c | 31 | ||||
-rw-r--r-- | core/Messenger.h | 18 | ||||
-rw-r--r-- | docs/commands.md | 25 | ||||
-rw-r--r-- | docs/using_tox.md | 38 | ||||
-rw-r--r-- | other/bootstrap_serverdaemon/CMakeLists.txt | 3 | ||||
-rw-r--r-- | other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c | 11 | ||||
-rw-r--r-- | other/bootstrap_serverdaemon/cmake/Modules/FindLibConfig.cmake | 73 | ||||
-rw-r--r-- | other/bootstrap_serverdaemon/server.cfg | 4 | ||||
-rw-r--r-- | start_guide.de.md | 40 | ||||
-rw-r--r-- | start_guide.md | 38 | ||||
-rw-r--r-- | testing/DHT_cryptosendfiletest.c | 4 | ||||
-rw-r--r-- | testing/nTox.c | 57 | ||||
-rw-r--r-- | testing/nTox_win32.c | 1 | ||||
-rw-r--r-- | testing/toxic/CMakeLists.txt | 3 | ||||
-rw-r--r-- | testing/toxic/friendlist.c | 125 | ||||
-rw-r--r-- | testing/toxic/main.c | 49 | ||||
-rw-r--r-- | testing/toxic/prompt.c | 109 |
22 files changed, 595 insertions, 82 deletions
@@ -12,3 +12,11 @@ install_manifest.txt | |||
12 | 12 | ||
13 | testing/data | 13 | testing/data |
14 | *~ | 14 | *~ |
15 | |||
16 | # Object files | ||
17 | *.o | ||
18 | |||
19 | # Executables | ||
20 | *.exe | ||
21 | *.out | ||
22 | *.app | ||
diff --git a/.travis.yml b/.travis.yml index 9de4e282..8e71c327 100644 --- a/.travis.yml +++ b/.travis.yml | |||
@@ -11,12 +11,17 @@ before_script: | |||
11 | - ./autogen.sh | 11 | - ./autogen.sh |
12 | - ./configure && make check -j3 | 12 | - ./configure && make check -j3 |
13 | - sudo make install | 13 | - sudo make install |
14 | - sudo ldconfig | ||
15 | - cd .. | 14 | - cd .. |
16 | # installing libconfig, needed for DHT_bootstrap_daemon | 15 | # installing libconfig, needed for DHT_bootstrap_daemon |
17 | - sudo sed -i 's/precise/quantal/' /etc/apt/sources.list # needed for libconfig-dev | 16 | - wget http://www.hyperrealm.com/libconfig/libconfig-1.4.9.tar.gz |
18 | - sudo apt-get update -qq | 17 | - tar -xvzf libconfig-1.4.9.tar.gz |
19 | - yes | sudo apt-get install libconfig-dev | 18 | - cd libconfig-1.4.9 |
19 | - ./configure && make -j3 | ||
20 | - sudo make install | ||
21 | - cd .. | ||
22 | # creating librarys' links and updating cache | ||
23 | - sudo ldconfig | ||
24 | |||
20 | 25 | ||
21 | script: | 26 | script: |
22 | - mkdir build && cd build | 27 | - mkdir build && cd build |
@@ -42,7 +42,17 @@ make | |||
42 | 42 | ||
43 | ###OSX: | 43 | ###OSX: |
44 | 44 | ||
45 | Much the same as above, remember to install the latest XCode and the developer tools (Preferences -> Downloads -> Command Line Tools). | 45 | ####Homebrew: |
46 | ``` | ||
47 | brew install libtool automake autoconf libconfig libsodium | ||
48 | cmake . | ||
49 | make | ||
50 | sudo make install | ||
51 | ``` | ||
52 | |||
53 | ####Non-homebrew: | ||
54 | |||
55 | Much the same as Linux, remember to install the latest XCode and the developer tools (Preferences -> Downloads -> Command Line Tools). | ||
46 | Users running Mountain Lion and the latest version of XCode (4.6.3) will also need to install libtool, automake and autoconf. | 56 | Users running Mountain Lion and the latest version of XCode (4.6.3) will also need to install libtool, automake and autoconf. |
47 | 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: | 57 | 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: |
48 | 58 | ||
@@ -6,27 +6,28 @@ With the rise of governmental monitoring programs, Tox aims to be an easy to use | |||
6 | 6 | ||
7 | 7 | ||
8 | 8 | ||
9 | **IRC**: #tox on Freenode, alternatively, you can use the [webchat](http://webchat.freenode.net/?channels=#tox).<br /> | 9 | **IRC**: #tox on freenode, alternatively, you can use the [webchat](http://webchat.freenode.net/?channels=#tox).<br /> |
10 | **Website**: [http://tox.im](http://tox.im) | 10 | **Website**: [http://tox.im](http://tox.im) |
11 | 11 | ||
12 | **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/> |
13 | **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) |
14 | 14 | ||
15 | 15 | **How to build Tox on Linux**: [YouTube video](http://www.youtube.com/watch?v=M4WXE4VKmyg)<br /> | |
16 | **How to use Tox on Windows**: [YouTube video](http://www.youtube.com/watch?v=qg_j_sDb6WQ) | ||
16 | 17 | ||
17 | ## The Complex Stuff: | 18 | ## The Complex Stuff: |
18 | + Tox must use UDP simply because you can't hole punch with TCP. It's possible, but it doesn't work all the time. | 19 | + Tox must use UDP simply because you can't hole punch with TCP. It's possible, but it doesn't work all the time. |
19 | + Every peer is represented as a byte string (the public key of the peer [client id]) | 20 | + Every peer is represented as a byte string (the public key of the peer [client id]) |
20 | + We're using torrent-style DHT so that peers can find the IP of the other peers when they have their ID. | 21 | + We're using torrent-style DHT so that peers can find the IP of the other peers when they have their ID. |
21 | + Once the client has the IP of that peer, they start initiating a secure connection with each other. (See [Crypto](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto)) | 22 | + Once the client has the IP of that peer, they start initiating a secure connection with each other. (See [Crypto](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto)) |
22 | + When both peers are securely connect with the encryption, they can securely exchange messages, initiate a video chat, send files, etc.<br /> | 23 | + When both peers are securely connected, they can exchange messages, initiate a video chat, send files, etc, all using encrypted communications.<br /> |
23 | + Current build status: [![Build Status](https://travis-ci.org/irungentoo/ProjectTox-Core.png?branch=master)](https://travis-ci.org/irungentoo/ProjectTox-Core) | 24 | + Current build status: [![Build Status](https://travis-ci.org/irungentoo/ProjectTox-Core.png?branch=master)](https://travis-ci.org/irungentoo/ProjectTox-Core) |
24 | 25 | ||
25 | ## Roadmap: | 26 | ## Roadmap: |
26 | - [x] Get our DHT working perfectly.(Done, needs large scale testing though.) | 27 | - [x] Get our DHT working perfectly.(Done, needs large scale testing though.) |
27 | - [x] Reliable connection (See Lossless_UDP protocol) to other peers according to client id. (Done, see DHT_sendfiletest.c for an example) | 28 | - [x] Reliable connection (See Lossless_UDP protocol) to other peers according to client id. (Done, see DHT_sendfiletest.c for an example) |
28 | - [x] Encryption. (Done) | 29 | - [x] Encryption. (Done) |
29 | - [ ] Get a simple text only im client working perfectly. (This is where we are) | 30 | - [ ] Get a simple text only IM client working perfectly. (This is where we are) |
30 | - [ ] Streaming media | 31 | - [ ] Streaming media |
31 | - [ ] ??? | 32 | - [ ] ??? |
32 | 33 | ||
diff --git a/core/Lossless_UDP.c b/core/Lossless_UDP.c index eb1314d1..6be8328f 100644 --- a/core/Lossless_UDP.c +++ b/core/Lossless_UDP.c | |||
@@ -308,12 +308,16 @@ IP_Port connection_ip(int connection_id) | |||
308 | /* returns the number of packets in the queue waiting to be successfully sent. */ | 308 | /* returns the number of packets in the queue waiting to be successfully sent. */ |
309 | uint32_t sendqueue(int connection_id) | 309 | uint32_t sendqueue(int connection_id) |
310 | { | 310 | { |
311 | if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) | ||
312 | return 0; | ||
311 | return connections[connection_id].sendbuff_packetnum - connections[connection_id].successful_sent; | 313 | return connections[connection_id].sendbuff_packetnum - connections[connection_id].successful_sent; |
312 | } | 314 | } |
313 | 315 | ||
314 | /* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */ | 316 | /* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */ |
315 | uint32_t recvqueue(int connection_id) | 317 | uint32_t recvqueue(int connection_id) |
316 | { | 318 | { |
319 | if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) | ||
320 | return 0; | ||
317 | return connections[connection_id].recv_packetnum - connections[connection_id].successful_read; | 321 | return connections[connection_id].recv_packetnum - connections[connection_id].successful_read; |
318 | } | 322 | } |
319 | 323 | ||
@@ -321,6 +325,8 @@ uint32_t recvqueue(int connection_id) | |||
321 | return -1 if no packet in queue */ | 325 | return -1 if no packet in queue */ |
322 | char id_packet(int connection_id) | 326 | char id_packet(int connection_id) |
323 | { | 327 | { |
328 | if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) | ||
329 | return -1; | ||
324 | if (recvqueue(connection_id) != 0 && connections[connection_id].status != 0) | 330 | if (recvqueue(connection_id) != 0 && connections[connection_id].status != 0) |
325 | return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0]; | 331 | return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0]; |
326 | return -1; | 332 | return -1; |
diff --git a/core/Messenger.c b/core/Messenger.c index 4c76dd30..872d7407 100644 --- a/core/Messenger.c +++ b/core/Messenger.c | |||
@@ -99,18 +99,21 @@ int getclient_id(int friend_id, uint8_t *client_id) | |||
99 | client_id is the client id of the friend | 99 | client_id is the client id of the friend |
100 | data is the data and length is the length | 100 | data is the data and length is the length |
101 | returns the friend number if success | 101 | returns the friend number if success |
102 | return -1 if failure. */ | 102 | return -1 if key length is wrong. |
103 | return -2 if user's own key | ||
104 | return -3 if already a friend | ||
105 | return -4 for other*/ | ||
103 | int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) | 106 | int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) |
104 | { | 107 | { |
105 | if (length == 0 || length >= | 108 | if (length == 0 || length >= |
106 | (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) | 109 | (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) |
107 | return -1; | 110 | return -1; |
108 | if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) | 111 | if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) |
109 | return -1; | 112 | return -2; |
110 | if (getfriend_id(client_id) != -1) | 113 | if (getfriend_id(client_id) != -1) |
111 | return -1; | 114 | return -3; |
112 | uint32_t i; | 115 | uint32_t i; |
113 | for (i = 0; i <= numfriends; ++i) { | 116 | for (i = 0; i <= numfriends; ++i) { /*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/ |
114 | if(friendlist[i].status == 0) { | 117 | if(friendlist[i].status == 0) { |
115 | DHT_addfriend(client_id); | 118 | DHT_addfriend(client_id); |
116 | friendlist[i].status = 1; | 119 | friendlist[i].status = 1; |
@@ -126,7 +129,7 @@ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) | |||
126 | return i; | 129 | return i; |
127 | } | 130 | } |
128 | } | 131 | } |
129 | return -1; | 132 | return -4; |
130 | } | 133 | } |
131 | 134 | ||
132 | int m_addfriend_norequest(uint8_t * client_id) | 135 | int m_addfriend_norequest(uint8_t * client_id) |
@@ -134,7 +137,7 @@ int m_addfriend_norequest(uint8_t * client_id) | |||
134 | if (getfriend_id(client_id) != -1) | 137 | if (getfriend_id(client_id) != -1) |
135 | return -1; | 138 | return -1; |
136 | uint32_t i; | 139 | uint32_t i; |
137 | for (i = 0; i <= numfriends; ++i) { | 140 | for (i = 0; i <= numfriends; ++i) {/*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/ |
138 | if(friendlist[i].status == 0) { | 141 | if(friendlist[i].status == 0) { |
139 | DHT_addfriend(client_id); | 142 | DHT_addfriend(client_id); |
140 | friendlist[i].status = 2; | 143 | friendlist[i].status = 2; |
@@ -164,7 +167,7 @@ int m_delfriend(int friendnumber) | |||
164 | memset(&friendlist[friendnumber], 0, sizeof(Friend)); | 167 | memset(&friendlist[friendnumber], 0, sizeof(Friend)); |
165 | uint32_t i; | 168 | uint32_t i; |
166 | for (i = numfriends; i != 0; --i) { | 169 | for (i = numfriends; i != 0; --i) { |
167 | if (friendlist[i].status != 0) | 170 | if (friendlist[i-1].status != 0) |
168 | break; | 171 | break; |
169 | } | 172 | } |
170 | numfriends = i; | 173 | numfriends = i; |
@@ -178,7 +181,7 @@ int m_delfriend(int friendnumber) | |||
178 | return 0 if there is no friend with that number */ | 181 | return 0 if there is no friend with that number */ |
179 | int m_friendstatus(int friendnumber) | 182 | int m_friendstatus(int friendnumber) |
180 | { | 183 | { |
181 | if (friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS) | 184 | if (friendnumber < 0 || friendnumber >= numfriends) |
182 | return 0; | 185 | return 0; |
183 | return friendlist[friendnumber].status; | 186 | return friendlist[friendnumber].status; |
184 | } | 187 | } |
@@ -188,7 +191,7 @@ int m_friendstatus(int friendnumber) | |||
188 | return 0 if it was not */ | 191 | return 0 if it was not */ |
189 | int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length) | 192 | int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length) |
190 | { | 193 | { |
191 | if (friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS) | 194 | if (friendnumber < 0 || friendnumber >= numfriends) |
192 | return 0; | 195 | return 0; |
193 | if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != 4) | 196 | if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != 4) |
194 | /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */ | 197 | /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */ |
@@ -240,6 +243,16 @@ int setname(uint8_t * name, uint16_t length) | |||
240 | return 0; | 243 | return 0; |
241 | } | 244 | } |
242 | 245 | ||
246 | /* get our nickname | ||
247 | put it in name | ||
248 | name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. | ||
249 | return the length of the name */ | ||
250 | uint16_t getself_name(uint8_t *name) | ||
251 | { | ||
252 | memcpy(name, self_name, self_name_length); | ||
253 | return self_name_length; | ||
254 | } | ||
255 | |||
243 | /* get name of friendnumber | 256 | /* get name of friendnumber |
244 | put it in name | 257 | put it in name |
245 | name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. | 258 | name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. |
diff --git a/core/Messenger.h b/core/Messenger.h index 7263901c..9ce96fb4 100644 --- a/core/Messenger.h +++ b/core/Messenger.h | |||
@@ -46,11 +46,14 @@ extern "C" { | |||
46 | to an absurdly large number later */ | 46 | to an absurdly large number later */ |
47 | 47 | ||
48 | /* add a friend | 48 | /* add a friend |
49 | set the data that will be sent along with friend request | 49 | set the data that will be sent along with friend request |
50 | client_id is the client id of the friend | 50 | client_id is the client id of the friend |
51 | data is the data and length is the length | 51 | data is the data and length is the length |
52 | returns the friend number if success | 52 | returns the friend number if success |
53 | return -1 if failure. */ | 53 | return -1 if key length is wrong. |
54 | return -2 if user's own key | ||
55 | return -3 if already a friend | ||
56 | return -4 for other*/ | ||
54 | int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length); | 57 | int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length); |
55 | 58 | ||
56 | 59 | ||
@@ -92,6 +95,11 @@ int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length); | |||
92 | return -1 if failure */ | 95 | return -1 if failure */ |
93 | int setname(uint8_t *name, uint16_t length); | 96 | int setname(uint8_t *name, uint16_t length); |
94 | 97 | ||
98 | /* get our nickname | ||
99 | put it in name | ||
100 | return the length of the name*/ | ||
101 | uint16_t getself_name(uint8_t *name); | ||
102 | |||
95 | /* get name of friendnumber | 103 | /* get name of friendnumber |
96 | put it in name | 104 | put it in name |
97 | name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. | 105 | name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. |
diff --git a/docs/commands.md b/docs/commands.md new file mode 100644 index 00000000..8669bb9b --- /dev/null +++ b/docs/commands.md | |||
@@ -0,0 +1,25 @@ | |||
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/using_tox.md b/docs/using_tox.md new file mode 100644 index 00000000..b4f4310d --- /dev/null +++ b/docs/using_tox.md | |||
@@ -0,0 +1,38 @@ | |||
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/CMakeLists.txt b/other/bootstrap_serverdaemon/CMakeLists.txt index a9cfdff7..512179f3 100644 --- a/other/bootstrap_serverdaemon/CMakeLists.txt +++ b/other/bootstrap_serverdaemon/CMakeLists.txt | |||
@@ -14,3 +14,6 @@ target_link_libraries(${exe_name} | |||
14 | ${LIBCONFIG_LIBRARY}) | 14 | ${LIBCONFIG_LIBRARY}) |
15 | 15 | ||
16 | linkCoreLibraries(${exe_name}) | 16 | linkCoreLibraries(${exe_name}) |
17 | |||
18 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") | ||
19 | find_package(LibConfig REQUIRED) | ||
diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c index 8e278b28..4f28fb3c 100644 --- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c +++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c | |||
@@ -123,11 +123,12 @@ void manage_keys(char *keys_file) | |||
123 | { | 123 | { |
124 | const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; | 124 | const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; |
125 | uint8_t keys[KEYS_SIZE]; | 125 | uint8_t keys[KEYS_SIZE]; |
126 | 126 | struct stat existence; | |
127 | /* TODO: stat the file before trying to open it. We aren't cave people! */ | 127 | FILE *keysf; |
128 | FILE *keysf = fopen(keys_file, "r"); | 128 | |
129 | if (keysf != NULL) { | 129 | /* Check if file exits, proceed to open and load keys */ |
130 | /* if file was opened successfully -- load keys */ | 130 | if(stat(keys_file,&existence) >= 0) { |
131 | keysf = fopen(keys_file, "r"); | ||
131 | size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keysf); | 132 | size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keysf); |
132 | if (read_size != KEYS_SIZE) { | 133 | if (read_size != KEYS_SIZE) { |
133 | printf("Error while reading the key file\nExiting.\n"); | 134 | printf("Error while reading the key file\nExiting.\n"); |
diff --git a/other/bootstrap_serverdaemon/cmake/Modules/FindLibConfig.cmake b/other/bootstrap_serverdaemon/cmake/Modules/FindLibConfig.cmake new file mode 100644 index 00000000..7d6270e6 --- /dev/null +++ b/other/bootstrap_serverdaemon/cmake/Modules/FindLibConfig.cmake | |||
@@ -0,0 +1,73 @@ | |||
1 | #Ref: https://github.com/schnorr/pajeng/blob/master/cmake/FindLibConfig.cmake | ||
2 | # | ||
3 | # This module defines | ||
4 | # LIBCONFIG_INCLUDE_DIR, where to find cppunit include files, etc. | ||
5 | # LIBCONFIG_LIBRARIES, the libraries to link against to use CppUnit. | ||
6 | # LIBCONFIG_STATIC_LIBRARIY_PATH | ||
7 | # LIBCONFIG_FOUND, If false, do not try to use CppUnit. | ||
8 | |||
9 | # also defined, but not for general use are | ||
10 | # LIBCONFIG_LIBRARY, where to find the CUnit library. | ||
11 | |||
12 | #MESSAGE("Searching for libconfig library") | ||
13 | |||
14 | FIND_PATH(LIBCONFIG_INCLUDE_DIR libconfig.h | ||
15 | /usr/local/include | ||
16 | /usr/include | ||
17 | ) | ||
18 | |||
19 | FIND_PATH(LIBCONFIGPP_INCLUDE_DIR libconfig.h++ | ||
20 | /usr/local/include | ||
21 | /usr/include | ||
22 | ) | ||
23 | |||
24 | FIND_LIBRARY(LIBCONFIG_LIBRARY config | ||
25 | /usr/local/lib | ||
26 | /usr/lib | ||
27 | ) | ||
28 | |||
29 | FIND_LIBRARY(LIBCONFIGPP_LIBRARY config++ | ||
30 | /usr/local/lib | ||
31 | /usr/lib | ||
32 | ) | ||
33 | |||
34 | FIND_LIBRARY(LIBCONFIG_STATIC_LIBRARY "libconfig${CMAKE_STATIC_LIBRARY_SUFFIX}" | ||
35 | /usr/local/lib | ||
36 | /usr/lib | ||
37 | ) | ||
38 | |||
39 | FIND_LIBRARY(LIBCONFIGPP_STATIC_LIBRARY "libconfig++${CMAKE_STATIC_LIBRARY_SUFFIX}" | ||
40 | /usr/local/lib | ||
41 | /usr/lib | ||
42 | ) | ||
43 | |||
44 | |||
45 | IF(LIBCONFIG_INCLUDE_DIR) | ||
46 | IF(LIBCONFIG_LIBRARY) | ||
47 | SET(LIBCONFIG_FOUND TRUE) | ||
48 | SET(LIBCONFIG_LIBRARIES ${LIBCONFIG_LIBRARY}) | ||
49 | SET(LIBCONFIG_STATIC_LIBRARY_PATH ${LIBCONFIG_STATIC_LIBRARY}) | ||
50 | ENDIF(LIBCONFIG_LIBRARY) | ||
51 | ENDIF(LIBCONFIG_INCLUDE_DIR) | ||
52 | |||
53 | IF(LIBCONFIGPP_INCLUDE_DIR) | ||
54 | IF(LIBCONFIGPP_LIBRARY) | ||
55 | SET(LIBCONFIGPP_FOUND TRUE) | ||
56 | SET(LIBCONFIGPP_LIBRARIES ${LIBCONFIGPP_LIBRARY}) | ||
57 | SET(LIBCONFIGPP_STATIC_LIBRARY_PATH ${LIBCONFIGPP_STATIC_LIBRARY}) | ||
58 | ENDIF(LIBCONFIGPP_LIBRARY) | ||
59 | ENDIF(LIBCONFIGPP_INCLUDE_DIR) | ||
60 | |||
61 | IF (LIBCONFIG_FOUND) | ||
62 | IF (NOT LibConfig_FIND_QUIETLY) | ||
63 | MESSAGE(STATUS "Found LibConfig++: ${LIBCONFIGPP_LIBRARIES}" ) | ||
64 | MESSAGE(STATUS "Found LibConfig: ${LIBCONFIG_LIBRARIES}") | ||
65 | MESSAGE(STATUS "static LibConfig path: ${LIBCONFIG_STATIC_LIBRARY_PATH}") | ||
66 | ENDIF (NOT LibConfig_FIND_QUIETLY) | ||
67 | ELSE (LIBCONFIG_FOUND) | ||
68 | IF (LibConfig_FIND_REQUIRED) | ||
69 | MESSAGE(SEND_ERROR "Could NOT find LibConfig") | ||
70 | ENDIF (LibConfig_FIND_REQUIRED) | ||
71 | ENDIF (LIBCONFIG_FOUND) | ||
72 | |||
73 | MARK_AS_ADVANCED(LIBCONFIG_INCLUDE_DIR LIBCONFIG_LIBRARIES) | ||
diff --git a/other/bootstrap_serverdaemon/server.cfg b/other/bootstrap_serverdaemon/server.cfg index 8ef516ca..527c2a72 100644 --- a/other/bootstrap_serverdaemon/server.cfg +++ b/other/bootstrap_serverdaemon/server.cfg | |||
@@ -6,11 +6,15 @@ port = 33445; | |||
6 | // The key file | 6 | // The key file |
7 | // make sure that the user who runs the server | 7 | // make sure that the user who runs the server |
8 | // does have permissions to read it/write to it | 8 | // does have permissions to read it/write to it |
9 | // Remember to replace the provided example with | ||
10 | // the directory the DHT server will run in. | ||
9 | keys_file = "/home/tom/.bootstrap_server.keys" | 11 | keys_file = "/home/tom/.bootstrap_server.keys" |
10 | 12 | ||
11 | // The PID file written to by bootstrap_server, | 13 | // The PID file written to by bootstrap_server, |
12 | // make sure that the user who runs the server | 14 | // make sure that the user who runs the server |
13 | // does have permissions to write to it | 15 | // does have permissions to write to it |
16 | // Remember to replace the provided example with | ||
17 | // the directory the DHT server will run in. | ||
14 | pid_file = "/home/tom/.bootstrap_server.pid"; | 18 | pid_file = "/home/tom/.bootstrap_server.pid"; |
15 | 19 | ||
16 | // The info of the node bootstap_server will | 20 | // The info of the node bootstap_server will |
diff --git a/start_guide.de.md b/start_guide.de.md new file mode 100644 index 00000000..7dfd52ca --- /dev/null +++ b/start_guide.de.md | |||
@@ -0,0 +1,40 @@ | |||
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 new file mode 100644 index 00000000..b4f4310d --- /dev/null +++ b/start_guide.md | |||
@@ -0,0 +1,38 @@ | |||
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/testing/DHT_cryptosendfiletest.c b/testing/DHT_cryptosendfiletest.c index c7c33531..888dac0f 100644 --- a/testing/DHT_cryptosendfiletest.c +++ b/testing/DHT_cryptosendfiletest.c | |||
@@ -186,7 +186,7 @@ int main(int argc, char *argv[]) | |||
186 | fclose(file2); | 186 | fclose(file2); |
187 | } | 187 | } |
188 | } | 188 | } |
189 | /* if buffer is empty and the connection timed out. */ | 189 | /* if buffer is empty and the connection timed out. */ |
190 | else if(is_cryptoconnected(inconnection) == 4) { | 190 | else if(is_cryptoconnected(inconnection) == 4) { |
191 | crypto_kill(inconnection); | 191 | crypto_kill(inconnection); |
192 | } | 192 | } |
@@ -209,7 +209,7 @@ int main(int argc, char *argv[]) | |||
209 | fclose(file2); | 209 | fclose(file2); |
210 | } | 210 | } |
211 | } | 211 | } |
212 | /* if buffer is empty and the connection timed out. */ | 212 | /* if buffer is empty and the connection timed out. */ |
213 | else if(is_cryptoconnected(connection) == 4) { | 213 | else if(is_cryptoconnected(connection) == 4) { |
214 | crypto_kill(connection); | 214 | crypto_kill(connection); |
215 | } | 215 | } |
diff --git a/testing/nTox.c b/testing/nTox.c index 97a39a12..6aef1d7b 100644 --- a/testing/nTox.c +++ b/testing/nTox.c | |||
@@ -35,6 +35,8 @@ | |||
35 | 35 | ||
36 | char lines[HISTORY][STRING_LENGTH]; | 36 | char lines[HISTORY][STRING_LENGTH]; |
37 | char line[STRING_LENGTH]; | 37 | char line[STRING_LENGTH]; |
38 | char *help = "[i] commands: /f ID (to add friend), /m friendnumber message (to send message), /s status (to change status)\n" | ||
39 | "[i] /l list (list friends), /h for help, /i for info, /n nick (to change nickname), /q (to quit)"; | ||
38 | int x,y; | 40 | int x,y; |
39 | 41 | ||
40 | uint8_t pending_requests[256][CLIENT_ID_SIZE]; | 42 | uint8_t pending_requests[256][CLIENT_ID_SIZE]; |
@@ -50,6 +52,7 @@ void new_lines(char *line) | |||
50 | do_refresh(); | 52 | do_refresh(); |
51 | } | 53 | } |
52 | 54 | ||
55 | |||
53 | void print_friendlist() | 56 | void print_friendlist() |
54 | { | 57 | { |
55 | char name[MAX_NAME_LENGTH]; | 58 | char name[MAX_NAME_LENGTH]; |
@@ -69,6 +72,26 @@ void print_friendlist() | |||
69 | } | 72 | } |
70 | } | 73 | } |
71 | 74 | ||
75 | char *format_message(char *message, int friendnum) | ||
76 | { | ||
77 | char name[MAX_NAME_LENGTH]; | ||
78 | if(friendnum != -1) { | ||
79 | getname(friendnum, (uint8_t*)name); | ||
80 | } else { | ||
81 | getself_name((uint8_t*)name); | ||
82 | } | ||
83 | char *msg = malloc(100+strlen(message)+strlen(name)+1); | ||
84 | time_t rawtime; | ||
85 | struct tm * timeinfo; | ||
86 | time ( &rawtime ); | ||
87 | timeinfo = localtime ( &rawtime ); | ||
88 | char* time = asctime(timeinfo); | ||
89 | size_t len = strlen(time); | ||
90 | time[len-1]='\0'; | ||
91 | sprintf(msg, "[%d] %s <%s> %s", friendnum, time, name, message); // timestamp | ||
92 | return msg; | ||
93 | } | ||
94 | |||
72 | void line_eval(char lines[HISTORY][STRING_LENGTH], char *line) | 95 | void line_eval(char lines[HISTORY][STRING_LENGTH], char *line) |
73 | { | 96 | { |
74 | if (line[0] == '/') { | 97 | if (line[0] == '/') { |
@@ -107,6 +130,8 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line) | |||
107 | int num = atoi(numstring); | 130 | int num = atoi(numstring); |
108 | if(m_sendmessage(num, (uint8_t*) message, sizeof(message)) != 1) { | 131 | if(m_sendmessage(num, (uint8_t*) message, sizeof(message)) != 1) { |
109 | new_lines("[i] could not send message"); | 132 | new_lines("[i] could not send message"); |
133 | } else { | ||
134 | new_lines(format_message(message, -1)); | ||
110 | } | 135 | } |
111 | } | 136 | } |
112 | else if (line[1] == 'n') { | 137 | else if (line[1] == 'n') { |
@@ -153,10 +178,31 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line) | |||
153 | } | 178 | } |
154 | 179 | ||
155 | else if (line[1] == 'h') { //help | 180 | else if (line[1] == 'h') { //help |
156 | new_lines("[i] commands: /f ID (to add friend), /m friendnumber message (to send message), /s status (to change status)"); | 181 | new_lines(help); |
157 | new_lines("[i] /l list (list friends), /h for help, /n nick (to change nickname), /q (to quit)"); | ||
158 | } | 182 | } |
159 | 183 | ||
184 | else if (line[1] == 'i') { //info | ||
185 | char idstring0[200]; | ||
186 | char idstring1[32][5]; | ||
187 | char idstring2[32][5]; | ||
188 | uint32_t i; | ||
189 | for(i = 0; i < 32; i++) | ||
190 | { | ||
191 | if(self_public_key[i] < 16) | ||
192 | strcpy(idstring1[i],"0"); | ||
193 | else | ||
194 | strcpy(idstring1[i], ""); | ||
195 | sprintf(idstring2[i], "%hhX",self_public_key[i]); | ||
196 | } | ||
197 | // | ||
198 | strcpy(idstring0,"[i] ID: "); | ||
199 | for (i=0; i<32; i++) { | ||
200 | strcat(idstring0,idstring1[i]); | ||
201 | strcat(idstring0,idstring2[i]); | ||
202 | } | ||
203 | new_lines(idstring0); | ||
204 | } | ||
205 | |||
160 | else if (line[1] == 'q') { //exit | 206 | else if (line[1] == 'q') { //exit |
161 | endwin(); | 207 | endwin(); |
162 | exit(EXIT_SUCCESS); | 208 | exit(EXIT_SUCCESS); |
@@ -255,7 +301,7 @@ void print_message(int friendnumber, uint8_t * string, uint16_t length) | |||
255 | size_t len = strlen(temp); | 301 | size_t len = strlen(temp); |
256 | temp[len-1]='\0'; | 302 | temp[len-1]='\0'; |
257 | sprintf(msg, "[%d] %s <%s> %s", friendnumber, temp, name, string); // timestamp | 303 | sprintf(msg, "[%d] %s <%s> %s", friendnumber, temp, name, string); // timestamp |
258 | new_lines(msg); | 304 | new_lines(format_message((char*)string, friendnumber)); |
259 | } | 305 | } |
260 | 306 | ||
261 | void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) { | 307 | void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) { |
@@ -344,8 +390,7 @@ int main(int argc, char *argv[]) | |||
344 | raw(); | 390 | raw(); |
345 | getmaxyx(stdscr,y,x); | 391 | getmaxyx(stdscr,y,x); |
346 | new_lines(idstring0); | 392 | new_lines(idstring0); |
347 | new_lines("[i] commands: /f ID (to add friend), /m friendnumber message (to send message), /s status (to change status)"); | 393 | new_lines(help); |
348 | new_lines("[i] /l list (list friends), /n nick (to change nickname), /q (to quit)"); | ||
349 | strcpy(line, ""); | 394 | strcpy(line, ""); |
350 | IP_Port bootstrap_ip_port; | 395 | IP_Port bootstrap_ip_port; |
351 | bootstrap_ip_port.port = htons(atoi(argv[2])); | 396 | bootstrap_ip_port.port = htons(atoi(argv[2])); |
diff --git a/testing/nTox_win32.c b/testing/nTox_win32.c index 3a9caaf5..a870c210 100644 --- a/testing/nTox_win32.c +++ b/testing/nTox_win32.c | |||
@@ -317,6 +317,7 @@ int main(int argc, char *argv[]) | |||
317 | } | 317 | } |
318 | 318 | ||
319 | doMessenger(); | 319 | doMessenger(); |
320 | Sleep(1); | ||
320 | } | 321 | } |
321 | 322 | ||
322 | return 0; | 323 | return 0; |
diff --git a/testing/toxic/CMakeLists.txt b/testing/toxic/CMakeLists.txt index 4f9785d5..c70babb7 100644 --- a/testing/toxic/CMakeLists.txt +++ b/testing/toxic/CMakeLists.txt | |||
@@ -5,7 +5,8 @@ set(exe_name toxic) | |||
5 | 5 | ||
6 | add_executable(${exe_name} | 6 | add_executable(${exe_name} |
7 | main.c | 7 | main.c |
8 | prompt.c) | 8 | prompt.c |
9 | friendlist.c) | ||
9 | 10 | ||
10 | target_link_libraries(${exe_name} | 11 | target_link_libraries(${exe_name} |
11 | curses) | 12 | curses) |
diff --git a/testing/toxic/friendlist.c b/testing/toxic/friendlist.c new file mode 100644 index 00000000..f8b8c840 --- /dev/null +++ b/testing/toxic/friendlist.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Toxic -- Tox Curses Client | ||
3 | */ | ||
4 | |||
5 | #include <curses.h> | ||
6 | #include <string.h> | ||
7 | #include <stdint.h> | ||
8 | #include <ctype.h> | ||
9 | |||
10 | #include "../../core/Messenger.h" | ||
11 | #include "../../core/network.h" | ||
12 | |||
13 | #include "windows.h" | ||
14 | |||
15 | #define MAX_FRIENDS_NUM 100 | ||
16 | |||
17 | typedef struct { | ||
18 | uint8_t name[MAX_NAME_LENGTH]; | ||
19 | uint8_t status[MAX_USERSTATUS_LENGTH]; | ||
20 | int num; | ||
21 | |||
22 | } friend_t; | ||
23 | |||
24 | static friend_t friends[MAX_FRIENDS_NUM]; | ||
25 | static int num_friends = 0; | ||
26 | |||
27 | |||
28 | void fix_name(uint8_t* name) { | ||
29 | |||
30 | // Remove all non alphanumeric characters. | ||
31 | uint8_t* p = name; | ||
32 | uint8_t* q = name; | ||
33 | |||
34 | while(*p != 0) { | ||
35 | if(isalnum(*p)) { | ||
36 | *q++ = *p; | ||
37 | } | ||
38 | |||
39 | p++; | ||
40 | } | ||
41 | |||
42 | *q = 0; | ||
43 | } | ||
44 | |||
45 | int friendlist_nickchange(int num, uint8_t* str, uint16_t len) { | ||
46 | |||
47 | if(len >= MAX_NAME_LENGTH || num >= num_friends) | ||
48 | return -1; | ||
49 | |||
50 | memcpy((char*) &friends[num].name, (char*) str, len); | ||
51 | friends[num].name[len] = 0; | ||
52 | fix_name(friends[num].name); | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | int friendlist_statuschange(int num, uint8_t* str, uint16_t len) { | ||
58 | |||
59 | if(len >= MAX_USERSTATUS_LENGTH || num >= num_friends) | ||
60 | return -1; | ||
61 | |||
62 | memcpy((char*) &friends[num].status, (char*) str, len); | ||
63 | friends[num].status[len] = 0; | ||
64 | fix_name(friends[num].status); | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | int friendlist_addfriend(int num) { | ||
70 | |||
71 | if(num_friends == MAX_FRIENDS_NUM) | ||
72 | return -1; | ||
73 | |||
74 | friends[num_friends].num = num; | ||
75 | getname(num, friends[num_friends].name); | ||
76 | strcpy((char*) friends[num_friends].name, "unknown"); | ||
77 | strcpy((char*) friends[num_friends].status, "unknown"); | ||
78 | |||
79 | num_friends++; | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static void friendlist_onKey(ToxWindow* self, int key) { | ||
84 | |||
85 | } | ||
86 | |||
87 | static void friendlist_onDraw(ToxWindow* self) { | ||
88 | size_t i; | ||
89 | |||
90 | wclear(self->window); | ||
91 | |||
92 | if(num_friends == 0) { | ||
93 | wprintw(self->window, "Empty. Add some friends! :-)\n"); | ||
94 | } | ||
95 | |||
96 | wprintw(self->window, "\n"); | ||
97 | |||
98 | for(i=0; i<num_friends; i++) { | ||
99 | wprintw(self->window, "[%d] ", friends[i].num); | ||
100 | |||
101 | attron(A_BOLD); | ||
102 | wprintw(self->window, "%s ", friends[i].name); | ||
103 | attroff(A_BOLD); | ||
104 | |||
105 | wprintw(self->window, "(%s)\n", friends[i].status); | ||
106 | } | ||
107 | |||
108 | wrefresh(self->window); | ||
109 | } | ||
110 | |||
111 | static void friendlist_onInit(ToxWindow* self) { | ||
112 | |||
113 | } | ||
114 | |||
115 | |||
116 | ToxWindow new_friendlist() { | ||
117 | ToxWindow ret; | ||
118 | |||
119 | ret.onKey = &friendlist_onKey; | ||
120 | ret.onDraw = &friendlist_onDraw; | ||
121 | ret.onInit = &friendlist_onInit; | ||
122 | strcpy(ret.title, "[friends]"); | ||
123 | |||
124 | return ret; | ||
125 | } | ||
diff --git a/testing/toxic/main.c b/testing/toxic/main.c index 0aad6777..e1d1ebd0 100644 --- a/testing/toxic/main.c +++ b/testing/toxic/main.c | |||
@@ -14,6 +14,12 @@ | |||
14 | #include "windows.h" | 14 | #include "windows.h" |
15 | 15 | ||
16 | extern ToxWindow new_prompt(); | 16 | extern ToxWindow new_prompt(); |
17 | extern ToxWindow new_friendlist(); | ||
18 | |||
19 | extern int friendlist_addfriend(int num); | ||
20 | extern int friendlist_nickchange(int num, uint8_t* str, uint16_t len); | ||
21 | extern int friendlist_statuschange(int num, uint8_t* str, uint16_t len); | ||
22 | |||
17 | extern int add_req(uint8_t* public_key); // XXX | 23 | extern int add_req(uint8_t* public_key); // XXX |
18 | 24 | ||
19 | #define TOXWINDOWS_MAX_NUM 32 | 25 | #define TOXWINDOWS_MAX_NUM 32 |
@@ -35,11 +41,19 @@ void on_message(int friendnumber, uint8_t* string, uint16_t length) { | |||
35 | } | 41 | } |
36 | 42 | ||
37 | void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) { | 43 | void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) { |
38 | wprintw(prompt->window, "\n(nick) %d: %s!\n", friendnumber, string); | 44 | wprintw(prompt->window, "\n(nickchange) %d: %s!\n", friendnumber, string); |
45 | |||
46 | friendlist_nickchange(friendnumber, string, length); | ||
39 | } | 47 | } |
40 | 48 | ||
41 | void on_statuschange(int friendnumber, uint8_t* string, uint16_t length) { | 49 | void on_statuschange(int friendnumber, uint8_t* string, uint16_t length) { |
42 | wprintw(prompt->window, "\n(status) %d: %s!\n", friendnumber, string); | 50 | wprintw(prompt->window, "\n(statuschange) %d: %s!\n", friendnumber, string); |
51 | |||
52 | friendlist_statuschange(friendnumber, string, length); | ||
53 | } | ||
54 | |||
55 | void on_friendadded(int friendnumber) { | ||
56 | friendlist_addfriend(friendnumber); | ||
43 | } | 57 | } |
44 | // CALLBACKS END | 58 | // CALLBACKS END |
45 | 59 | ||
@@ -95,7 +109,7 @@ static void init_windows() { | |||
95 | w_num = 0; | 109 | w_num = 0; |
96 | w_active = 0; | 110 | w_active = 0; |
97 | 111 | ||
98 | if(add_window(new_prompt()) == -1) { | 112 | if(add_window(new_prompt()) == -1 || add_window(new_friendlist()) == -1) { |
99 | fprintf(stderr, "add_window() failed.\n"); | 113 | fprintf(stderr, "add_window() failed.\n"); |
100 | 114 | ||
101 | endwin(); | 115 | endwin(); |
@@ -134,14 +148,18 @@ static void load_data() { | |||
134 | 148 | ||
135 | if(buf == NULL) { | 149 | if(buf == NULL) { |
136 | fprintf(stderr, "malloc() failed.\n"); | 150 | fprintf(stderr, "malloc() failed.\n"); |
151 | |||
137 | fclose(fd); | 152 | fclose(fd); |
153 | endwin(); | ||
138 | exit(1); | 154 | exit(1); |
139 | } | 155 | } |
140 | 156 | ||
141 | if(fread(buf, len, 1, fd) != 1){ | 157 | if(fread(buf, len, 1, fd) != 1){ |
142 | fprintf(stderr, "fread() failed.\n"); | 158 | fprintf(stderr, "fread() failed.\n"); |
159 | |||
143 | free(buf); | 160 | free(buf); |
144 | fclose(fd); | 161 | fclose(fd); |
162 | endwin(); | ||
145 | exit(1); | 163 | exit(1); |
146 | } | 164 | } |
147 | 165 | ||
@@ -153,6 +171,7 @@ static void load_data() { | |||
153 | 171 | ||
154 | if(buf == NULL) { | 172 | if(buf == NULL) { |
155 | fprintf(stderr, "malloc() failed.\n"); | 173 | fprintf(stderr, "malloc() failed.\n"); |
174 | endwin(); | ||
156 | exit(1); | 175 | exit(1); |
157 | } | 176 | } |
158 | 177 | ||
@@ -161,14 +180,18 @@ static void load_data() { | |||
161 | fd = fopen("data", "w"); | 180 | fd = fopen("data", "w"); |
162 | if(fd == NULL) { | 181 | if(fd == NULL) { |
163 | fprintf(stderr, "fopen() failed.\n"); | 182 | fprintf(stderr, "fopen() failed.\n"); |
183 | |||
164 | free(buf); | 184 | free(buf); |
185 | endwin(); | ||
165 | exit(1); | 186 | exit(1); |
166 | } | 187 | } |
167 | 188 | ||
168 | if(fwrite(buf, len, 1, fd) != 1){ | 189 | if(fwrite(buf, len, 1, fd) != 1){ |
169 | fprintf(stderr, "fwrite() failed.\n"); | 190 | fprintf(stderr, "fwrite() failed.\n"); |
191 | |||
170 | free(buf); | 192 | free(buf); |
171 | fclose(fd); | 193 | fclose(fd); |
194 | endwin(); | ||
172 | exit(1); | 195 | exit(1); |
173 | } | 196 | } |
174 | } | 197 | } |
@@ -186,12 +209,16 @@ static void draw_bar() { | |||
186 | 209 | ||
187 | move(LINES - 1, 0); | 210 | move(LINES - 1, 0); |
188 | 211 | ||
212 | attron(COLOR_PAIR(3) | A_BOLD); | ||
213 | printw(" TOXIC 1.0 |"); | ||
214 | attroff(COLOR_PAIR(3) | A_BOLD); | ||
215 | |||
189 | for(i=0; i<w_num; i++) { | 216 | for(i=0; i<w_num; i++) { |
190 | if(i == w_active) { | 217 | if(i == w_active) { |
191 | attron(A_BOLD); | 218 | attron(A_BOLD); |
192 | } | 219 | } |
193 | 220 | ||
194 | printw(" %s ", windows[i].title); | 221 | printw(" %s", windows[i].title); |
195 | 222 | ||
196 | if(i == w_active) { | 223 | if(i == w_active) { |
197 | attroff(A_BOLD); | 224 | attroff(A_BOLD); |
@@ -201,6 +228,11 @@ static void draw_bar() { | |||
201 | refresh(); | 228 | refresh(); |
202 | } | 229 | } |
203 | 230 | ||
231 | void prepare_window(WINDOW* w) { | ||
232 | mvwin(w, 0, 0); | ||
233 | wresize(w, LINES-2, COLS); | ||
234 | } | ||
235 | |||
204 | int main(int argc, char* argv[]) { | 236 | int main(int argc, char* argv[]) { |
205 | int ch; | 237 | int ch; |
206 | ToxWindow* a; | 238 | ToxWindow* a; |
@@ -211,14 +243,21 @@ int main(int argc, char* argv[]) { | |||
211 | init_windows(); | 243 | init_windows(); |
212 | 244 | ||
213 | while(true) { | 245 | while(true) { |
246 | // Update tox. | ||
214 | do_tox(); | 247 | do_tox(); |
215 | 248 | ||
249 | // Draw. | ||
216 | a = &windows[w_active]; | 250 | a = &windows[w_active]; |
251 | prepare_window(a->window); | ||
217 | a->onDraw(a); | 252 | a->onDraw(a); |
218 | draw_bar(); | 253 | draw_bar(); |
219 | 254 | ||
255 | // Handle input. | ||
220 | ch = getch(); | 256 | ch = getch(); |
221 | if(ch != ERR) { | 257 | if(ch == '\t') { |
258 | w_active = (w_active + 1) % w_num; | ||
259 | } | ||
260 | else if(ch != ERR) { | ||
222 | a->onKey(a, ch); | 261 | a->onKey(a, ch); |
223 | } | 262 | } |
224 | 263 | ||
diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c index 4a59cc7b..0cd10730 100644 --- a/testing/toxic/prompt.c +++ b/testing/toxic/prompt.c | |||
@@ -15,6 +15,8 @@ | |||
15 | uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX | 15 | 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); | ||
19 | |||
18 | // XXX: | 20 | // XXX: |
19 | int add_req(uint8_t* public_key) { | 21 | int add_req(uint8_t* public_key) { |
20 | memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE); | 22 | memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE); |
@@ -40,7 +42,6 @@ static int prompt_buf_pos=0; | |||
40 | 42 | ||
41 | static void execute(ToxWindow* self, char* cmd) { | 43 | static void execute(ToxWindow* self, char* cmd) { |
42 | 44 | ||
43 | // quit/exit: Exit program. | ||
44 | if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit")) { | 45 | if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit")) { |
45 | endwin(); | 46 | endwin(); |
46 | exit(0); | 47 | exit(0); |
@@ -53,33 +54,32 @@ static void execute(ToxWindow* self, char* cmd) { | |||
53 | 54 | ||
54 | ip = strchr(cmd, ' '); | 55 | ip = strchr(cmd, ' '); |
55 | if(ip == NULL) { | 56 | if(ip == NULL) { |
57 | wprintw(self->window, "Invalid syntax.\n"); | ||
56 | return; | 58 | return; |
57 | } | 59 | } |
58 | |||
59 | ip++; | 60 | ip++; |
60 | 61 | ||
61 | port = strchr(ip, ' '); | 62 | port = strchr(ip, ' '); |
62 | if(port == NULL) { | 63 | if(port == NULL) { |
64 | wprintw(self->window, "Invalid syntax.\n"); | ||
63 | return; | 65 | return; |
64 | } | 66 | } |
65 | |||
66 | port[0] = 0; | 67 | port[0] = 0; |
67 | port++; | 68 | port++; |
68 | 69 | ||
69 | key = strchr(port, ' '); | 70 | key = strchr(port, ' '); |
70 | if(key == NULL) { | 71 | if(key == NULL) { |
72 | wprintw(self->window, "Invalid syntax.\n"); | ||
71 | return; | 73 | return; |
72 | } | 74 | } |
73 | |||
74 | key[0] = 0; | 75 | key[0] = 0; |
75 | key++; | 76 | key++; |
76 | 77 | ||
77 | if(atoi(port) == 0) { | 78 | if(atoi(port) == 0) { |
79 | wprintw(self->window, "Invalid syntax.\n"); | ||
78 | return; | 80 | return; |
79 | } | 81 | } |
80 | 82 | ||
81 | wprintw(self->window, "ip=%s, port=%s, key=%s\n", ip, port, key); | ||
82 | |||
83 | dht.port = htons(atoi(port)); | 83 | dht.port = htons(atoi(port)); |
84 | 84 | ||
85 | int resolved_address = resolve_addr(ip); | 85 | int resolved_address = resolve_addr(ip); |
@@ -91,38 +91,62 @@ static void execute(ToxWindow* self, char* cmd) { | |||
91 | DHT_bootstrap(dht, hex_string_to_bin(key)); | 91 | DHT_bootstrap(dht, hex_string_to_bin(key)); |
92 | } | 92 | } |
93 | else if(!strncmp(cmd, "add ", strlen("add "))) { | 93 | else if(!strncmp(cmd, "add ", strlen("add "))) { |
94 | uint8_t id_bin[32]; | ||
95 | size_t i; | ||
96 | char xx[3]; | ||
97 | uint32_t x; | ||
98 | |||
94 | char* id; | 99 | char* id; |
95 | char* msg; | 100 | char* msg; |
96 | int num; | 101 | int num; |
97 | 102 | ||
98 | id = strchr(cmd, ' '); | 103 | id = strchr(cmd, ' '); |
99 | |||
100 | if(id == NULL) { | 104 | if(id == NULL) { |
105 | wprintw(self->window, "Invalid syntax.\n"); | ||
101 | return; | 106 | return; |
102 | } | 107 | } |
103 | |||
104 | id++; | 108 | id++; |
105 | 109 | ||
106 | msg = strchr(id, ' '); | 110 | msg = strchr(id, ' '); |
107 | if(msg == NULL) { | 111 | if(msg != NULL) { |
112 | msg[0] = 0; | ||
113 | msg++; | ||
114 | } | ||
115 | else msg = ""; | ||
116 | |||
117 | if(strlen(id) != 2*32) { | ||
118 | wprintw(self->window, "Invalid ID length.\n"); | ||
108 | return; | 119 | return; |
109 | } | 120 | } |
110 | 121 | ||
111 | msg[0] = 0; | 122 | for(i=0; i<32; i++) { |
112 | msg++; | 123 | xx[0] = id[2*i]; |
124 | xx[1] = id[2*i+1]; | ||
125 | xx[2] = '\0'; | ||
126 | |||
127 | if(sscanf(xx, "%02x", &x) != 1) { | ||
128 | wprintw(self->window, "Invalid ID.\n"); | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | id_bin[i] = x; | ||
133 | } | ||
134 | |||
135 | num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); | ||
113 | 136 | ||
114 | num = m_addfriend((uint8_t*) id, (uint8_t*) msg, strlen(msg)+1); | ||
115 | wprintw(self->window, "Friend added as %d.\n", num); | 137 | wprintw(self->window, "Friend added as %d.\n", num); |
138 | on_friendadded(num); | ||
116 | } | 139 | } |
117 | else if(!strncmp(cmd, "status ", strlen("status "))) { | 140 | else if(!strncmp(cmd, "status ", strlen("status "))) { |
118 | char* msg; | 141 | char* msg; |
119 | 142 | ||
120 | msg = strchr(cmd, ' '); | 143 | msg = strchr(cmd, ' '); |
121 | if(msg == NULL) { | 144 | if(msg == NULL) { |
145 | wprintw(self->window, "Invalid syntax.\n"); | ||
122 | return; | 146 | return; |
123 | } | 147 | } |
124 | |||
125 | msg++; | 148 | msg++; |
149 | |||
126 | m_set_userstatus((uint8_t*) msg, strlen(msg)+1); | 150 | m_set_userstatus((uint8_t*) msg, strlen(msg)+1); |
127 | wprintw(self->window, "Status set to: %s.\n", msg); | 151 | wprintw(self->window, "Status set to: %s.\n", msg); |
128 | } | 152 | } |
@@ -133,33 +157,22 @@ static void execute(ToxWindow* self, char* cmd) { | |||
133 | if(nick == NULL) { | 157 | if(nick == NULL) { |
134 | return; | 158 | return; |
135 | } | 159 | } |
136 | |||
137 | nick++; | 160 | nick++; |
161 | |||
138 | setname((uint8_t*) nick, strlen(nick)+1); | 162 | setname((uint8_t*) nick, strlen(nick)+1); |
139 | wprintw(self->window, "Nickname set to: %s.\n", nick); | 163 | wprintw(self->window, "Nickname set to: %s.\n", nick); |
140 | } | 164 | } |
141 | else if(!strcmp(cmd, "myid")) { | 165 | else if(!strcmp(cmd, "myid")) { |
142 | // XXX: Clean this up | 166 | char id[32*2 + 1] = {0}; |
143 | char idstring0[200]; | 167 | size_t i; |
144 | char idstring1[32][5]; | 168 | |
145 | char idstring2[32][5]; | 169 | for(i=0; i<32; i++) { |
146 | uint32_t i; | 170 | char xx[3]; |
147 | 171 | snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); | |
148 | for(i = 0; i < 32; i++) { | 172 | strcat(id, xx); |
149 | if(self_public_key[i] < 16) | ||
150 | strcpy(idstring1[i], "0"); | ||
151 | else | ||
152 | strcpy(idstring1[i], ""); | ||
153 | |||
154 | sprintf(idstring2[i], "%hhX", self_public_key[i]); | ||
155 | } | 173 | } |
156 | 174 | ||
157 | for (i=0; i<32; i++) { | 175 | wprintw(self->window, "%s\n", id); |
158 | strcat(idstring0, idstring1[i]); | ||
159 | strcat(idstring0, idstring2[i]); | ||
160 | } | ||
161 | |||
162 | wprintw(self->window, "%s\n", idstring0); | ||
163 | } | 176 | } |
164 | else if(!strncmp(cmd, "accept ", strlen("accept "))) { | 177 | else if(!strncmp(cmd, "accept ", strlen("accept "))) { |
165 | char* id; | 178 | char* id; |
@@ -167,17 +180,26 @@ static void execute(ToxWindow* self, char* cmd) { | |||
167 | 180 | ||
168 | id = strchr(cmd, ' '); | 181 | id = strchr(cmd, ' '); |
169 | if(id == NULL) { | 182 | if(id == NULL) { |
183 | wprintw(self->window, "Invalid syntax.\n"); | ||
170 | return; | 184 | return; |
171 | } | 185 | } |
172 | id++; | 186 | id++; |
173 | 187 | ||
174 | num = atoi(id); | 188 | num = atoi(id); |
175 | if(num >= num_requests) { | 189 | if(num >= num_requests) { |
190 | wprintw(self->window, "Invalid syntax.\n"); | ||
176 | return; | 191 | return; |
177 | } | 192 | } |
178 | 193 | ||
179 | num = m_addfriend_norequest(pending_requests[num]); | 194 | num = m_addfriend_norequest(pending_requests[num]); |
180 | wprintw(self->window, "Friend accepted as: %d.\n", num); | 195 | |
196 | if(num == -1) { | ||
197 | wprintw(self->window, "Failed to add friend.\n"); | ||
198 | } | ||
199 | else { | ||
200 | wprintw(self->window, "Friend accepted as: %d.\n", num); | ||
201 | on_friendadded(num); | ||
202 | } | ||
181 | } | 203 | } |
182 | else if(!strncmp(cmd, "msg ", strlen("msg "))) { | 204 | else if(!strncmp(cmd, "msg ", strlen("msg "))) { |
183 | char* id; | 205 | char* id; |
@@ -186,16 +208,16 @@ static void execute(ToxWindow* self, char* cmd) { | |||
186 | id = strchr(cmd, ' '); | 208 | id = strchr(cmd, ' '); |
187 | 209 | ||
188 | if(id == NULL) { | 210 | if(id == NULL) { |
211 | wprintw(self->window, "Invalid syntax.\n"); | ||
189 | return; | 212 | return; |
190 | } | 213 | } |
191 | |||
192 | id++; | 214 | id++; |
193 | 215 | ||
194 | msg = strchr(id, ' '); | 216 | msg = strchr(id, ' '); |
195 | if(msg == NULL) { | 217 | if(msg == NULL) { |
218 | wprintw(self->window, "Invalid syntax.\n"); | ||
196 | return; | 219 | return; |
197 | } | 220 | } |
198 | |||
199 | msg[0] = 0; | 221 | msg[0] = 0; |
200 | msg++; | 222 | msg++; |
201 | 223 | ||
@@ -206,6 +228,9 @@ static void execute(ToxWindow* self, char* cmd) { | |||
206 | wprintw(self->window, "Message successfully sent.\n"); | 228 | wprintw(self->window, "Message successfully sent.\n"); |
207 | } | 229 | } |
208 | } | 230 | } |
231 | else { | ||
232 | wprintw(self->window, "Invalid syntax.\n"); | ||
233 | } | ||
209 | } | 234 | } |
210 | 235 | ||
211 | static void prompt_onKey(ToxWindow* self, int key) { | 236 | static void prompt_onKey(ToxWindow* self, int key) { |
@@ -242,9 +267,6 @@ static void prompt_onKey(ToxWindow* self, int key) { | |||
242 | static void prompt_onDraw(ToxWindow* self) { | 267 | static void prompt_onDraw(ToxWindow* self) { |
243 | int x, y; | 268 | int x, y; |
244 | 269 | ||
245 | mvwin(self->window,0,0); | ||
246 | wresize(self->window, LINES-2, COLS); | ||
247 | |||
248 | getyx(self->window, y, x); | 270 | getyx(self->window, y, x); |
249 | (void) x; | 271 | (void) x; |
250 | 272 | ||
@@ -265,11 +287,18 @@ static void print_usage(ToxWindow* self) { | |||
265 | 287 | ||
266 | wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n"); | 288 | wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n"); |
267 | wprintw(self->window, " add <id> <message> : Add friend\n"); | 289 | wprintw(self->window, " add <id> <message> : Add friend\n"); |
290 | wprintw(self->window, " msg <number> <message> : Send message\n"); | ||
268 | wprintw(self->window, " status <message> : Set your status\n"); | 291 | wprintw(self->window, " status <message> : Set your status\n"); |
269 | wprintw(self->window, " nick <nickname> : Set your nickname\n"); | 292 | wprintw(self->window, " nick <nickname> : Set your nickname\n"); |
270 | wprintw(self->window, " accept <number> : Accept friend request\n"); | 293 | wprintw(self->window, " accept <number> : Accept friend request\n"); |
271 | wprintw(self->window, " myid : Print your ID\n"); | 294 | wprintw(self->window, " myid : Print your ID\n"); |
272 | wprintw(self->window, " quit/exit : Exit program\n"); | 295 | wprintw(self->window, " quit/exit : Exit program\n"); |
296 | |||
297 | |||
298 | wattron(self->window, A_BOLD); | ||
299 | wprintw(self->window, "Use the TAB key to navigate through the tabs.\n"); | ||
300 | wattroff(self->window, A_BOLD); | ||
301 | |||
273 | wattroff(self->window, COLOR_PAIR(2)); | 302 | wattroff(self->window, COLOR_PAIR(2)); |
274 | } | 303 | } |
275 | 304 | ||