summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcharmlesscoin <charmlesscoin@gmail.com>2013-08-06 20:58:42 -0400
committercharmlesscoin <charmlesscoin@gmail.com>2013-08-06 20:58:42 -0400
commitc644ccd28782e9d74f5962a97a0973551fb7afe2 (patch)
tree42f892aea55a6394d5d6ff0dbace2214675cbd71
parent95a3f69580749b8fcabf92cc2ace757d61fa34de (diff)
parentd04f2d0e51931db5fbd8c672c44bb1e59fc58b79 (diff)
Merge branch 'master' of git://github.com/irungentoo/ProjectTox-Core
-rw-r--r--cmake/FindLIBCONFIG.cmake7
-rw-r--r--core/DHT.c142
-rw-r--r--core/DHT.h2
-rw-r--r--core/LAN_discovery.c4
-rw-r--r--core/Messenger.c6
-rw-r--r--core/packets.h37
-rw-r--r--core/ping.c127
-rw-r--r--core/ping.h5
-rw-r--r--core/util.c13
-rw-r--r--core/util.h3
-rw-r--r--testing/misc_tools.c12
-rw-r--r--testing/misc_tools.h142
-rw-r--r--testing/nTox.c2
-rw-r--r--testing/toxic/chat.c120
-rw-r--r--testing/toxic/friendlist.c142
-rw-r--r--testing/toxic/main.c321
-rw-r--r--testing/toxic/prompt.c238
-rw-r--r--testing/toxic/windows.h8
18 files changed, 804 insertions, 527 deletions
diff --git a/cmake/FindLIBCONFIG.cmake b/cmake/FindLIBCONFIG.cmake
index d5018240..b3ae4d11 100644
--- a/cmake/FindLIBCONFIG.cmake
+++ b/cmake/FindLIBCONFIG.cmake
@@ -5,7 +5,12 @@
5# LIBCONFIG_FOUND 5# LIBCONFIG_FOUND
6# 6#
7 7
8FIND_PATH(LIBCONFIG_INCLUDE_DIR NAMES libconfig.h) 8if (UNIX)
9 find_package(PkgConfig QUIET)
10 pkg_check_modules(_LIBCONFIG QUIET libconfig)
11endif ()
12
13FIND_PATH(LIBCONFIG_INCLUDE_DIR NAMES libconfig.h HINTS ${_LIBCONFIG_INCLUDEDIR})
9 14
10FIND_LIBRARY(LIBCONFIG_LIBRARY NAMES config) 15FIND_LIBRARY(LIBCONFIG_LIBRARY NAMES config)
11 16
diff --git a/core/DHT.c b/core/DHT.c
index f0b32df5..b5224b8f 100644
--- a/core/DHT.c
+++ b/core/DHT.c
@@ -24,6 +24,7 @@
24/*----------------------------------------------------------------------------------*/ 24/*----------------------------------------------------------------------------------*/
25 25
26#include "DHT.h" 26#include "DHT.h"
27#include "packets.h"
27#include "ping.h" 28#include "ping.h"
28 29
29/* maximum number of clients stored per friend. */ 30/* maximum number of clients stored per friend. */
@@ -351,7 +352,7 @@ static int replace_good( Client_data * list,
351/* Attempt to add client with ip_port and client_id to the friends client list 352/* Attempt to add client with ip_port and client_id to the friends client list
352 * and close_clientlist 353 * and close_clientlist
353 */ 354 */
354static void addto_lists(IP_Port ip_port, uint8_t * client_id) 355void addto_lists(IP_Port ip_port, uint8_t * client_id)
355{ 356{
356 uint32_t i; 357 uint32_t i;
357 358
@@ -472,71 +473,6 @@ static uint64_t add_gettingnodes(IP_Port ip_port)
472 return 0; 473 return 0;
473} 474}
474 475
475/* send a ping request, only works if none has been sent to that ip/port
476 * in the last 5 seconds.
477 */
478static int pingreq(IP_Port ip_port, uint8_t * public_key)
479{
480 /* check if packet is gonna be sent to ourself */
481 if(id_equal(public_key, self_public_key) || is_pinging(ip_port, 0))
482 return 1;
483
484 uint64_t ping_id = add_ping(ip_port);
485 if(ping_id == 0)
486 return 1;
487
488 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING];
489 uint8_t encrypt[sizeof(ping_id) + ENCRYPTION_PADDING];
490 uint8_t nonce[crypto_box_NONCEBYTES];
491 random_nonce(nonce);
492
493 int len = encrypt_data( public_key,
494 self_secret_key,
495 nonce,
496 (uint8_t *)&ping_id,
497 sizeof(ping_id),
498 encrypt );
499
500 if(len != sizeof(ping_id) + ENCRYPTION_PADDING)
501 return -1;
502
503 data[0] = 0;
504 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
505 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
506 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
507
508 return sendpacket(ip_port, data, sizeof(data));
509}
510
511/* send a ping response */
512static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id)
513{
514 /* check if packet is gonna be sent to ourself */
515 if(id_equal(public_key, self_public_key))
516 return 1;
517
518 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING];
519 uint8_t encrypt[sizeof(ping_id) + ENCRYPTION_PADDING];
520 uint8_t nonce[crypto_box_NONCEBYTES];
521 random_nonce(nonce);
522
523 int len = encrypt_data( public_key,
524 self_secret_key, nonce,
525 (uint8_t *)&ping_id,
526 sizeof(ping_id),
527 encrypt );
528
529 if(len != sizeof(ping_id) + ENCRYPTION_PADDING)
530 return -1;
531
532 data[0] = 1;
533 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
534 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
535 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
536
537 return sendpacket(ip_port, data, sizeof(data));
538}
539
540/* send a getnodes request */ 476/* send a getnodes request */
541static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) 477static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id)
542{ 478{
@@ -618,62 +554,6 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id,
618 return sendpacket(ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); 554 return sendpacket(ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
619} 555}
620 556
621/* Packet handling functions, one to handle each types of packets we receive
622 * Returns 0 if handled correctly, 1 if packet is bad.
623 */
624static int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source)
625{
626 uint64_t ping_id;
627 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING)
628 return 1;
629
630 /* check if packet is from ourself. */
631 if(id_equal(packet + 1, self_public_key))
632 return 1;
633
634 int len = decrypt_data( packet + 1,
635 self_secret_key,
636 packet + 1 + CLIENT_ID_SIZE,
637 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
638 sizeof(ping_id) + ENCRYPTION_PADDING,
639 (uint8_t *)&ping_id );
640
641 if(len != sizeof(ping_id))
642 return 1;
643
644 pingres(source, packet + 1, ping_id);
645 pingreq(source, packet + 1); /* TODO: make this smarter? */
646
647 return 0;
648}
649
650static int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source)
651{
652 uint64_t ping_id;
653 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING)
654 return 1;
655
656 /* check if packet is from ourself. */
657 if(id_equal(packet + 1, self_public_key))
658 return 1;
659
660 int len = decrypt_data( packet + 1,
661 self_secret_key,
662 packet + 1 + CLIENT_ID_SIZE,
663 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
664 sizeof(ping_id) + ENCRYPTION_PADDING,
665 (uint8_t *)&ping_id );
666
667 if(len != sizeof(ping_id))
668 return 1;
669
670 if(is_pinging(source, ping_id)) {
671 addto_lists(source, packet + 1);
672 return 0;
673 }
674 return 1;
675}
676
677static int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source) 557static int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
678{ 558{
679 uint64_t ping_id; 559 uint64_t ping_id;
@@ -701,7 +581,7 @@ static int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
701 memcpy(&ping_id, plain, sizeof(ping_id)); 581 memcpy(&ping_id, plain, sizeof(ping_id));
702 sendnodes(source, packet + 1, plain + sizeof(ping_id), ping_id); 582 sendnodes(source, packet + 1, plain + sizeof(ping_id), ping_id);
703 583
704 pingreq(source, packet + 1); /* TODO: make this smarter? */ 584 send_ping_request(source, (clientid_t*) (packet + 1)); /* TODO: make this smarter? */
705 585
706 return 0; 586 return 0;
707} 587}
@@ -741,7 +621,7 @@ static int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source)
741 621
742 uint32_t i; 622 uint32_t i;
743 for(i = 0; i < num_nodes; ++i) { 623 for(i = 0; i < num_nodes; ++i) {
744 pingreq(nodes_list[i].ip_port, nodes_list[i].client_id); 624 send_ping_request(nodes_list[i].ip_port, (clientid_t*) &nodes_list[i].client_id);
745 returnedip_ports(nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); 625 returnedip_ports(nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
746 } 626 }
747 627
@@ -831,8 +711,8 @@ static void doDHTFriends(void)
831 /* if node is not dead. */ 711 /* if node is not dead. */
832 if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { 712 if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) {
833 if ((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { 713 if ((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) {
834 pingreq( friends_list[i].client_list[j].ip_port, 714 send_ping_request( friends_list[i].client_list[j].ip_port,
835 friends_list[i].client_list[j].client_id ); 715 (clientid_t*) &friends_list[i].client_list[j].client_id );
836 friends_list[i].client_list[j].last_pinged = temp_time; 716 friends_list[i].client_list[j].last_pinged = temp_time;
837 } 717 }
838 /* if node is good. */ 718 /* if node is good. */
@@ -869,8 +749,8 @@ static void doClose(void)
869 /* if node is not dead. */ 749 /* if node is not dead. */
870 if (!is_timeout(temp_time, close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) { 750 if (!is_timeout(temp_time, close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) {
871 if ((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { 751 if ((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) {
872 pingreq( close_clientlist[i].ip_port, 752 send_ping_request( close_clientlist[i].ip_port,
873 close_clientlist[i].client_id ); 753 (clientid_t*) &close_clientlist[i].client_id );
874 close_clientlist[i].last_pinged = temp_time; 754 close_clientlist[i].last_pinged = temp_time;
875 } 755 }
876 /* if node is good. */ 756 /* if node is good. */
@@ -1151,7 +1031,7 @@ static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t
1151 /*TODO: improve port guessing algorithm*/ 1031 /*TODO: improve port guessing algorithm*/
1152 uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1); 1032 uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1);
1153 IP_Port pinging = {ip, htons(port)}; 1033 IP_Port pinging = {ip, htons(port)};
1154 pingreq(pinging, friends_list[friend_num].client_id); 1034 send_ping_request(pinging, (clientid_t*) &friends_list[friend_num].client_id);
1155 } 1035 }
1156 friends_list[friend_num].punching_index = i; 1036 friends_list[friend_num].punching_index = i;
1157} 1037}
@@ -1198,10 +1078,10 @@ int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
1198{ 1078{
1199 switch (packet[0]) { 1079 switch (packet[0]) {
1200 case 0: 1080 case 0:
1201 return handle_pingreq(packet, length, source); 1081 return handle_ping_request(packet, length, source);
1202 1082
1203 case 1: 1083 case 1:
1204 return handle_pingres(packet, length, source); 1084 return handle_ping_response(packet, length, source);
1205 1085
1206 case 2: 1086 case 2:
1207 return handle_getnodes(packet, length, source); 1087 return handle_getnodes(packet, length, source);
diff --git a/core/DHT.h b/core/DHT.h
index 0edaebf3..2308abd8 100644
--- a/core/DHT.h
+++ b/core/DHT.h
@@ -104,6 +104,8 @@ int DHT_load(uint8_t *data, uint32_t size);
104 returns 1 if we are */ 104 returns 1 if we are */
105int DHT_isconnected(); 105int DHT_isconnected();
106 106
107void addto_lists(IP_Port ip_port, uint8_t * client_id);
108
107#ifdef __cplusplus 109#ifdef __cplusplus
108} 110}
109#endif 111#endif
diff --git a/core/LAN_discovery.c b/core/LAN_discovery.c
index 55953685..26b3930c 100644
--- a/core/LAN_discovery.c
+++ b/core/LAN_discovery.c
@@ -70,6 +70,10 @@ static uint32_t get_broadcast(void)
70 } 70 }
71 } 71 }
72 close(sock); 72 close(sock);
73 if(sock_holder == NULL) {
74 perror("[!] no broadcast device found");
75 return 0;
76 }
73 77
74 return sock_holder->sin_addr.s_addr; 78 return sock_holder->sin_addr.s_addr;
75} 79}
diff --git a/core/Messenger.c b/core/Messenger.c
index d8bf3413..5532c9cc 100644
--- a/core/Messenger.c
+++ b/core/Messenger.c
@@ -116,7 +116,7 @@ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
116 return FAERR_ALREADYSENT; 116 return FAERR_ALREADYSENT;
117 117
118 uint32_t i; 118 uint32_t i;
119 for (i = 0; i <= numfriends && i <= MAX_NUM_FRIENDS; ++i) { /*TODO: dynamic memory allocation to allow for more than MAX_NUM_FRIENDS friends */ 119 for (i = 0; i < numfriends && i < MAX_NUM_FRIENDS; ++i) { /*TODO: dynamic memory allocation to allow for more than MAX_NUM_FRIENDS friends */
120 if(friendlist[i].status == NOFRIEND) { 120 if(friendlist[i].status == NOFRIEND) {
121 DHT_addfriend(client_id); 121 DHT_addfriend(client_id);
122 friendlist[i].status = FRIEND_ADDED; 122 friendlist[i].status = FRIEND_ADDED;
@@ -141,7 +141,7 @@ int m_addfriend_norequest(uint8_t * client_id)
141 if (getfriend_id(client_id) != -1) 141 if (getfriend_id(client_id) != -1)
142 return -1; 142 return -1;
143 uint32_t i; 143 uint32_t i;
144 for (i = 0; i <= numfriends && i <= MAX_NUM_FRIENDS; ++i) { /*TODO: dynamic memory allocation to allow for more than MAX_NUM_FRIENDS friends */ 144 for (i = 0; i < numfriends && i < MAX_NUM_FRIENDS; ++i) { /*TODO: dynamic memory allocation to allow for more than MAX_NUM_FRIENDS friends */
145 if(friendlist[i].status == NOFRIEND) { 145 if(friendlist[i].status == NOFRIEND) {
146 DHT_addfriend(client_id); 146 DHT_addfriend(client_id);
147 friendlist[i].status = FRIEND_REQUESTED; 147 friendlist[i].status = FRIEND_REQUESTED;
@@ -352,7 +352,7 @@ static int send_userstatus(int friendnumber, uint8_t * status, uint16_t length)
352 memcpy(thepacket + 2, status, length); 352 memcpy(thepacket + 2, status, length);
353 thepacket[0] = PACKET_ID_USERSTATUS; 353 thepacket[0] = PACKET_ID_USERSTATUS;
354 thepacket[1] = self_userstatus_kind; 354 thepacket[1] = self_userstatus_kind;
355 int written = write_cryptpacket(friendlist[friendnumber].crypt_connection_id, thepacket, length + 1); 355 int written = write_cryptpacket(friendlist[friendnumber].crypt_connection_id, thepacket, length + 2);
356 free(thepacket); 356 free(thepacket);
357 return written; 357 return written;
358} 358}
diff --git a/core/packets.h b/core/packets.h
new file mode 100644
index 00000000..222b1425
--- /dev/null
+++ b/core/packets.h
@@ -0,0 +1,37 @@
1/*
2 * packet.h -- Packet structure
3 *
4 * This file is donated to the Tox Project.
5 * Copyright 2013 plutooo
6 */
7
8typedef struct {
9 uint8_t id[CLIENT_ID_SIZE];
10
11} __attribute__((packed)) clientid_t;
12
13typedef enum {
14 PACKET_PING_REQ = 0,
15 PACKET_PING_RES = 1
16
17} packetid_t;
18
19// Ping packet
20typedef struct {
21 uint8_t magic;
22 clientid_t client_id;
23 uint8_t nonce[crypto_box_NONCEBYTES];
24 uint64_t ping_id;
25 uint8_t padding[ENCRYPTION_PADDING];
26
27} __attribute__((packed)) pingreq_t;
28
29// Pong packet
30typedef struct {
31 uint8_t magic;
32 clientid_t client_id;
33 uint8_t nonce[crypto_box_NONCEBYTES];
34 uint64_t ping_id;
35 uint8_t padding[ENCRYPTION_PADDING];
36
37} __attribute__((packed)) pingres_t;
diff --git a/core/ping.c b/core/ping.c
index ffabe221..6a1fbb7e 100644
--- a/core/ping.c
+++ b/core/ping.c
@@ -8,6 +8,9 @@
8#include <stdbool.h> 8#include <stdbool.h>
9#include <stdint.h> 9#include <stdint.h>
10 10
11#include "DHT.h"
12#include "net_crypto.h"
13#include "packets.h"
11#include "network.h" 14#include "network.h"
12#include "util.h" 15#include "util.h"
13 16
@@ -20,10 +23,12 @@ typedef struct {
20 uint64_t timestamp; 23 uint64_t timestamp;
21} pinged_t; 24} pinged_t;
22 25
23static pinged_t pings[PING_NUM_MAX]; 26static pinged_t pings[PING_NUM_MAX];
24static size_t num_pings; 27static size_t num_pings;
25static size_t pos_pings; 28static size_t pos_pings;
29static clientid_t* self_id = (clientid_t*) &self_public_key;
26 30
31extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; // DHT.c
27 32
28void init_ping() 33void init_ping()
29{ 34{
@@ -51,15 +56,16 @@ static void remove_timeouts() // O(n)
51 new_num--; 56 new_num--;
52 } 57 }
53 // Break here because list is sorted. 58 // Break here because list is sorted.
54 else 59 else {
55 break; 60 break;
61 }
56 } 62 }
57 63
58 num_pings = new_num; 64 num_pings = new_num;
59 pos_pings = new_pos % PING_NUM_MAX; 65 pos_pings = new_pos % PING_NUM_MAX;
60} 66}
61 67
62uint64_t add_ping(IP_Port ipp) // O(n) 68uint64_t add_ping(IP_Port ipp) // O(n)
63{ 69{
64 size_t p; 70 size_t p;
65 71
@@ -94,6 +100,7 @@ bool is_pinging(IP_Port ipp, uint64_t ping_id) // O(n) TODO: replace this with
94 for (i=0; i<num_pings; i++) { 100 for (i=0; i<num_pings; i++) {
95 id = (pos_pings + i) % PING_NUM_MAX; 101 id = (pos_pings + i) % PING_NUM_MAX;
96 102
103 // ping_id = 0 means match any id
97 if ((ipp_eq(pings[id].ipp, ipp) || ipp.ip.i == 0) && (pings[id].id == ping_id || ping_id == 0)) { 104 if ((ipp_eq(pings[id].ipp, ipp) || ipp.ip.i == 0) && (pings[id].id == ping_id || ping_id == 0)) {
98 return true; 105 return true;
99 } 106 }
@@ -101,3 +108,113 @@ bool is_pinging(IP_Port ipp, uint64_t ping_id) // O(n) TODO: replace this with
101 108
102 return false; 109 return false;
103} 110}
111
112int send_ping_request(IP_Port ipp, clientid_t* client_id)
113{
114 pingreq_t pk;
115 int rc;
116 uint64_t ping_id;
117
118 if (is_pinging(ipp, 0) || id_eq(client_id, self_id))
119 return 1;
120
121 // Generate random ping_id
122 ping_id = add_ping(ipp);
123
124 pk.magic = PACKET_PING_REQ;
125 id_cpy(&pk.client_id, self_id); // Our pubkey
126 random_nonce((uint8_t*) &pk.nonce); // Generate random nonce
127
128 // Encrypt ping_id using recipient privkey
129 rc = encrypt_data((uint8_t*) client_id,
130 self_secret_key,
131 (uint8_t*) &pk.nonce,
132 (uint8_t*) &ping_id, sizeof(ping_id),
133 (uint8_t*) &pk.ping_id);
134
135 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING)
136 return 1;
137
138 return sendpacket(ipp, (uint8_t*) &pk, sizeof(pk));
139}
140
141int send_ping_response(IP_Port ipp, clientid_t* client_id, uint64_t ping_id)
142{
143 pingres_t pk;
144 int rc;
145
146 if (id_eq(client_id, self_id))
147 return 1;
148
149 pk.magic = PACKET_PING_RES;
150 id_cpy(&pk.client_id, self_id); // Our pubkey
151 random_nonce((uint8_t*) &pk.nonce); // Generate random nonce
152
153 // Encrypt ping_id using recipient privkey
154 rc = encrypt_data((uint8_t*) client_id,
155 self_secret_key,
156 (uint8_t*) &pk.nonce,
157 (uint8_t*) &ping_id, sizeof(ping_id),
158 (uint8_t*) &pk.ping_id);
159
160 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING)
161 return 1;
162
163 return sendpacket(ipp, (uint8_t*) &pk, sizeof(pk));
164}
165
166int handle_ping_request(uint8_t* packet, uint32_t length, IP_Port source)
167{
168 pingreq_t* p = (pingreq_t*) packet;
169 int rc;
170 uint64_t ping_id;
171
172 if (length != sizeof(pingreq_t) || id_eq(&p->client_id, self_id))
173 return 1;
174
175 // Decrypt ping_id
176 rc = decrypt_data((uint8_t*) &p->client_id,
177 self_secret_key,
178 (uint8_t*) &p->nonce,
179 (uint8_t*) &p->ping_id,
180 sizeof(ping_id) + ENCRYPTION_PADDING,
181 (uint8_t*) &ping_id);
182
183 if (rc != sizeof(ping_id))
184 return 1;
185
186 // Send response
187 send_ping_response(source, &p->client_id, ping_id);
188 send_ping_request(source, &p->client_id); // Make this smarter?
189
190 return 0;
191}
192
193int handle_ping_response(uint8_t* packet, uint32_t length, IP_Port source)
194{
195 pingres_t* p = (pingres_t*) packet;
196 int rc;
197 uint64_t ping_id;
198
199 if (length != sizeof(pingres_t) || id_eq(&p->client_id, self_id))
200 return 1;
201
202 // Decrypt ping_id
203 rc = decrypt_data((uint8_t*) &p->client_id,
204 self_secret_key,
205 (uint8_t*) &p->nonce,
206 (uint8_t*) &p->ping_id,
207 sizeof(ping_id) + ENCRYPTION_PADDING,
208 (uint8_t*) &ping_id);
209
210 if (rc != sizeof(ping_id))
211 return 1;
212
213 // Make sure ping_id is correct
214 if(!is_pinging(source, ping_id))
215 return 1;
216
217 // Associate source ip with client_id
218 addto_lists(source, (uint8_t*) &p->client_id);
219 return 0;
220}
diff --git a/core/ping.h b/core/ping.h
index 1d23df97..2cab7d59 100644
--- a/core/ping.h
+++ b/core/ping.h
@@ -10,4 +10,7 @@
10void init_ping(); 10void init_ping();
11uint64_t add_ping(IP_Port ipp); 11uint64_t add_ping(IP_Port ipp);
12bool is_pinging(IP_Port ipp, uint64_t ping_id); 12bool is_pinging(IP_Port ipp, uint64_t ping_id);
13 13int send_ping_request(IP_Port ipp, clientid_t* client_id);
14int send_ping_response(IP_Port ipp, clientid_t* client_id, uint64_t ping_id);
15int handle_ping_request(uint8_t* packet, uint32_t length, IP_Port source);
16int handle_ping_response(uint8_t* packet, uint32_t length, IP_Port source);
diff --git a/core/util.c b/core/util.c
index 4ce9271e..d201bcb4 100644
--- a/core/util.c
+++ b/core/util.c
@@ -9,7 +9,8 @@
9#include <stdint.h> 9#include <stdint.h>
10#include <stdbool.h> 10#include <stdbool.h>
11 11
12#include "network.h" 12#include "DHT.h"
13#include "packets.h"
13 14
14uint64_t now() 15uint64_t now()
15{ 16{
@@ -32,3 +33,13 @@ bool ipp_eq(IP_Port a, IP_Port b)
32{ 33{
33 return (a.ip.i == b.ip.i) && (a.port == b.port); 34 return (a.ip.i == b.ip.i) && (a.port == b.port);
34} 35}
36
37bool id_eq(clientid_t* dest, clientid_t* src)
38{
39 return memcmp(dest, src, sizeof(clientid_t)) == 0;
40}
41
42void id_cpy(clientid_t* dest, clientid_t* src)
43{
44 memcpy(dest, src, sizeof(clientid_t));
45}
diff --git a/core/util.h b/core/util.h
index aab2ead9..a93be08a 100644
--- a/core/util.h
+++ b/core/util.h
@@ -8,3 +8,6 @@
8uint64_t now(); 8uint64_t now();
9uint64_t random_64b(); 9uint64_t random_64b();
10bool ipp_eq(IP_Port a, IP_Port b); 10bool ipp_eq(IP_Port a, IP_Port b);
11bool id_eq(clientid_t* dest, clientid_t* src);
12void id_cpy(clientid_t* dest, clientid_t* src);
13
diff --git a/testing/misc_tools.c b/testing/misc_tools.c
index aa546a88..fa7f42c9 100644
--- a/testing/misc_tools.c
+++ b/testing/misc_tools.c
@@ -25,7 +25,11 @@
25 25
26#include <string.h> 26#include <string.h>
27#include <stdlib.h> 27#include <stdlib.h>
28#include <stdio.h> /* for sscanf */ 28#include <stdio.h>
29
30#ifdef DEBUG
31#include <assert.h>
32#endif // DEBUG
29 33
30/* TODO: rewrite */ 34/* TODO: rewrite */
31unsigned char * hex_string_to_bin(char hex_string[]) 35unsigned char * hex_string_to_bin(char hex_string[])
@@ -39,3 +43,9 @@ unsigned char * hex_string_to_bin(char hex_string[])
39 43
40 return val; 44 return val;
41} 45}
46
47
48
49
50
51
diff --git a/testing/misc_tools.h b/testing/misc_tools.h
index 5079e15d..eb09693e 100644
--- a/testing/misc_tools.h
+++ b/testing/misc_tools.h
@@ -25,5 +25,145 @@
25#define MISC_TOOLS_H 25#define MISC_TOOLS_H
26 26
27unsigned char * hex_string_to_bin(char hex_string[]); 27unsigned char * hex_string_to_bin(char hex_string[]);
28 28
29/* WARNING(msg) takes a printf()-styled string and prints it
30 * with some additional details.
31 * ERROR(exit_status, msg) does the same thing as WARNING(), but
32 * also exits the program with the given exit status.
33 * Examples:
34 * WARNING("<insert warning message here>");
35 * int exit_status = 2;
36 * ERROR(exit_status, "exiting with status %i", exit_status);
37 */
38#ifdef DEBUG
39 #include <assert.h>
40 #include <stdio.h>
41 #include <string.h>
42
43 #define DEBUG_PRINT(str, ...) do { \
44 char msg[1000]; \
45 sprintf(msg, "%s(): line %d (file %s): %s%%c\n", __FUNCTION__, __LINE__, __FILE__, str); \
46 fprintf(stderr, msg, __VA_ARGS__); \
47 } while (0)
48
49 #define WARNING(...) do { \
50 fprintf(stderr, "warning in "); \
51 DEBUG_PRINT(__VA_ARGS__, ' '); \
52 } while (0)
53
54 #define ERROR(exit_status, ...) do { \
55 fprintf(stderr, "error in "); \
56 DEBUG_PRINT(__VA_ARGS__, ' '); \
57 exit(exit_status); \
58 } while (0)
59#else
60 #define WARNING(...)
61 #define ERROR(...)
62#endif // DEBUG
63
64/************************Linked List***********************
65 * This is a simple linked list implementation, very similar
66 * to Linux kernel's /include/linux/list.h (which we can't
67 * use because Tox is GPLv3 and Linux is GPLv2.)
68 *
69 * TODO: Make the lists easier to use with some sweat pre-
70 * processor syntactic sugar.
71 **********************************************************/
72
73/* Example usage
74
75This sample program makes a new struct which contains a
76character and a tox_list_t. It then prompts a user for
77input until he enters q or e. It then adds each character
78to the list, and uses a special for loop to print them.
79It then removes all the 'z' characters, and prints the list
80again.
81
82//Notice that the data to be put in the list *contains* tox_list_t;
83//usually, this is the other way around!
84typedef struct tox_string {
85 char c;
86 tox_list_t tox_lst; //Notice that tox_lst is *NOT* a pointer.
87} tox_string_t;
88
89int main()
90{
91 tox_list_t head;
92 tox_list_new(&head); //initialize head
93
94 //input a new character, until user enters q or e
95 char c = '\0';
96 while (c != 'q' && c != 'e') {
97 scanf("%c", &c);
98 tox_string_t* tmp = malloc(sizeof(tox_string_t));
99 tmp->c = c;
100 tox_list_add(&head, &tmp->tox_lst); //add it to the list
101 }
102
103TOX_LIST_FOR_EACH() takes a struct tox_list and a name for a temporary pointer to use in the loop.
104
105TOX_LIST_GET_VALUE() uses magic to return an instance of a structure that contains tox_list_t.
106You have to give it a temporary tox_string_t, name of tox_list_t member inside our structure (tox_lst),
107and the type of structure to return.
108
109 TOX_LIST_FOR_EACH(head, tmp)
110 printf("%c", TOX_LIST_GET_VALUE(*tmp, tox_lst, tox_string_t).c);
111
112 TOX_LIST_FOR_EACH(head, tmp) {
113 if (TOX_LIST_GET_VALUE(*tmp, tox_lst, tox_string_t).c == 'z') {
114 //If you delete tmp, you have to quit the loop, or it will go on infinitly.
115 //This will be fixed later on.
116 tox_list_remove(tmp);
117 break;
118 }
119 }
120
121 printf("\n");
122 TOX_LIST_FOR_EACH(head, tmp)
123 printf("%c", TOX_LIST_GET_VALUE(*tmp, tox_lst, tox_string_t).c);
124
125
126 return 0;
127}
128*/
129
130#define MEMBER_OFFSET(var_name_in_parent, parent_type) \
131 (&(((parent_type*)0)->var_name_in_parent))
132
133#define GET_PARENT(var, var_name_in_parent, parent_type) \
134 (*((parent_type*)((uint64_t)(&(var)) - (uint64_t)(MEMBER_OFFSET(var_name_in_parent, parent_type)))))
135
136#define TOX_LIST_FOR_EACH(lst, tmp_name) \
137 for (tox_list_t* tmp_name = lst.next; tmp_name != &lst; tmp_name = tmp_name->next)
138
139#define TOX_LIST_GET_VALUE(tmp_name, name_in_parent, parent_type) GET_PARENT(tmp_name, name_in_parent, parent_type)
140
141typedef struct tox_list {
142 struct tox_list *prev, *next;
143} tox_list_t;
144
145/* Returns a new tox_list_t. */
146static inline void tox_list_new(tox_list_t* lst) {
147 lst->prev = lst->next = lst;
148}
149
150/* Inserts a new tox_lst after lst and returns it. */
151static inline void tox_list_add(tox_list_t* lst, tox_list_t* new_lst) {
152 tox_list_new(new_lst);
153
154 new_lst->next = lst->next;
155 new_lst->next->prev = new_lst;
156
157 lst->next = new_lst;
158 new_lst->prev = lst;
159}
160
161static inline void tox_list_remove(tox_list_t* lst) {
162#ifdef DEBUG /* TODO: check how debugging is done in Tox. */
163 assert(lst->next != lst && lst->prev != lst);
164#endif
165 lst->prev->next = lst->next;
166 lst->next->prev = lst->prev;
167}
168
29#endif // MISC_TOOLS_H 169#endif // MISC_TOOLS_H
diff --git a/testing/nTox.c b/testing/nTox.c
index 63d0c32e..ecdba1e3 100644
--- a/testing/nTox.c
+++ b/testing/nTox.c
@@ -410,6 +410,8 @@ void load_key(char *path)
410 } 410 }
411 } 411 }
412 412
413 if(fclose(data_file) < 0)
414 perror("[!] fclose failed");
413 return; 415 return;
414 416
415FILE_ERROR: 417FILE_ERROR:
diff --git a/testing/toxic/chat.c b/testing/toxic/chat.c
index da1f9f4a..20c01620 100644
--- a/testing/toxic/chat.c
+++ b/testing/toxic/chat.c
@@ -16,41 +16,39 @@
16 16
17typedef struct { 17typedef struct {
18 int friendnum; 18 int friendnum;
19
20 char line[256]; 19 char line[256];
21 size_t pos; 20 size_t pos;
22
23 WINDOW* history; 21 WINDOW* history;
24 WINDOW* linewin; 22 WINDOW* linewin;
25
26} ChatContext; 23} ChatContext;
27 24
28extern void fix_name(uint8_t* name); 25extern int active_window;
29void print_help(ChatContext* self);
30void execute(ToxWindow* self, ChatContext* ctx, char* cmd);
31 26
32static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) { 27extern void del_window(ToxWindow *w, int f_num);
33 ChatContext* ctx = (ChatContext*) self->x; 28extern void fix_name(uint8_t *name);
29void print_help(ChatContext *self);
30void execute(ToxWindow *self, ChatContext *ctx, char *cmd);
31
32static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len)
33{
34 ChatContext *ctx = (ChatContext*) self->x;
34 uint8_t nick[MAX_NAME_LENGTH] = {0}; 35 uint8_t nick[MAX_NAME_LENGTH] = {0};
35
36 time_t now; 36 time_t now;
37 time(&now); 37 time(&now);
38 struct tm * timeinfo; 38 struct tm * timeinfo;
39 timeinfo = localtime(&now); 39 timeinfo = localtime(&now);
40 40
41 if(ctx->friendnum != num) 41 if (ctx->friendnum != num)
42 return; 42 return;
43 43
44 getname(num, (uint8_t*) &nick); 44 getname(num, (uint8_t*) &nick);
45
46 msg[len-1] = '\0'; 45 msg[len-1] = '\0';
47 nick[MAX_NAME_LENGTH-1] = '\0'; 46 nick[MAX_NAME_LENGTH-1] = '\0';
48
49 fix_name(msg); 47 fix_name(msg);
50 fix_name(nick); 48 fix_name(nick);
51 49
52 wattron(ctx->history, COLOR_PAIR(2)); 50 wattron(ctx->history, COLOR_PAIR(2));
53 wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); 51 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
54 wattroff(ctx->history, COLOR_PAIR(2)); 52 wattroff(ctx->history, COLOR_PAIR(2));
55 wattron(ctx->history, COLOR_PAIR(4)); 53 wattron(ctx->history, COLOR_PAIR(4));
56 wprintw(ctx->history, "%s: ", nick); 54 wprintw(ctx->history, "%s: ", nick);
@@ -62,15 +60,14 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len)
62 flash(); 60 flash();
63} 61}
64 62
65static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t len) { 63static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len)
66 ChatContext* ctx = (ChatContext*) self->x; 64{
67 65 ChatContext *ctx = (ChatContext*) self->x;
68 if(ctx->friendnum != num) 66 if (ctx->friendnum != num)
69 return; 67 return;
70 68
71 nick[len-1] = '\0'; 69 nick[len-1] = '\0';
72 fix_name(nick); 70 fix_name(nick);
73
74 snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num); 71 snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num);
75 72
76 wattron(ctx->history, COLOR_PAIR(3)); 73 wattron(ctx->history, COLOR_PAIR(3));
@@ -78,7 +75,8 @@ static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t
78 wattroff(ctx->history, COLOR_PAIR(3)); 75 wattroff(ctx->history, COLOR_PAIR(3));
79} 76}
80 77
81static void chat_onStatusChange(ToxWindow* self, int num, uint8_t* status, uint16_t len) { 78static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint16_t len)
79{
82 80
83} 81}
84 82
@@ -87,45 +85,43 @@ int string_is_empty(char *string)
87{ 85{
88 int rc = 0; 86 int rc = 0;
89 char *copy = strdup(string); 87 char *copy = strdup(string);
90
91 rc = ((strtok(copy, " ") == NULL) ? 1:0); 88 rc = ((strtok(copy, " ") == NULL) ? 1:0);
92 free(copy); 89 free(copy);
93
94 return rc; 90 return rc;
95} 91}
96 92
97static void chat_onKey(ToxWindow* self, int key) { 93static void chat_onKey(ToxWindow *self, int key)
98 ChatContext* ctx = (ChatContext*) self->x; 94{
99 95 ChatContext *ctx = (ChatContext*) self->x;
100 time_t now; 96 time_t now;
101 time(&now); 97 time(&now);
102 struct tm * timeinfo; 98 struct tm * timeinfo;
103 timeinfo = localtime(&now); 99 timeinfo = localtime(&now);
104 100
105 /* PRINTABLE characters: Add to line */ 101 /* Add printable characters to line */
106 if(isprint(key)) { 102 if (isprint(key)) {
107 if(ctx->pos != sizeof(ctx->line)-1) { 103 if (ctx->pos != sizeof(ctx->line)-1) {
108 ctx->line[ctx->pos++] = key; 104 ctx->line[ctx->pos++] = key;
109 ctx->line[ctx->pos] = '\0'; 105 ctx->line[ctx->pos] = '\0';
110 } 106 }
111 } 107 }
112 108
113 /* RETURN key: Execute command or print line */ 109 /* RETURN key: Execute command or print line */
114 else if(key == '\n') { 110 else if (key == '\n') {
115 if (ctx->line[0] == '/') 111 if (ctx->line[0] == '/')
116 execute(self, ctx, ctx->line); 112 execute(self, ctx, ctx->line);
117 else { 113 else {
118 if(!string_is_empty(ctx->line)) { 114 if (!string_is_empty(ctx->line)) {
119 /* make sure the string has at least non-space character */ 115 /* make sure the string has at least non-space character */
120 wattron(ctx->history, COLOR_PAIR(2)); 116 wattron(ctx->history, COLOR_PAIR(2));
121 wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); 117 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
122 wattroff(ctx->history, COLOR_PAIR(2)); 118 wattroff(ctx->history, COLOR_PAIR(2));
123 wattron(ctx->history, COLOR_PAIR(1)); 119 wattron(ctx->history, COLOR_PAIR(1));
124 wprintw(ctx->history, "you: ", ctx->line); 120 wprintw(ctx->history, "you: ", ctx->line);
125 wattroff(ctx->history, COLOR_PAIR(1)); 121 wattroff(ctx->history, COLOR_PAIR(1));
126 wprintw(ctx->history, "%s\n", ctx->line); 122 wprintw(ctx->history, "%s\n", ctx->line);
127 } 123 }
128 if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) { 124 if (m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) {
129 wattron(ctx->history, COLOR_PAIR(3)); 125 wattron(ctx->history, COLOR_PAIR(3));
130 wprintw(ctx->history, " * Failed to send message.\n"); 126 wprintw(ctx->history, " * Failed to send message.\n");
131 wattroff(ctx->history, COLOR_PAIR(3)); 127 wattroff(ctx->history, COLOR_PAIR(3));
@@ -136,29 +132,32 @@ static void chat_onKey(ToxWindow* self, int key) {
136 } 132 }
137 133
138 /* BACKSPACE key: Remove one character from line */ 134 /* BACKSPACE key: Remove one character from line */
139 else if(key == 0x107 || key == 0x8 || key == 0x7f) { 135 else if (key == 0x107 || key == 0x8 || key == 0x7f) {
140 if(ctx->pos != 0) { 136 if (ctx->pos != 0) {
141 ctx->line[--ctx->pos] = '\0'; 137 ctx->line[--ctx->pos] = '\0';
142 } 138 }
143 } 139 }
144} 140}
145 141
146void execute(ToxWindow* self, ChatContext* ctx, char* cmd) 142void execute(ToxWindow *self, ChatContext *ctx, char *cmd)
147{ 143{
148 if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { 144 if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) {
149 wclear(self->window); 145 wclear(self->window);
150 wclear(ctx->history); 146 wclear(ctx->history);
151 } 147 }
148
152 else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h")) 149 else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h"))
153 print_help(ctx); 150 print_help(ctx);
151
154 else if (!strcmp(cmd, "/quit") || !strcmp(cmd, "/exit") || !strcmp(cmd, "/q")) { 152 else if (!strcmp(cmd, "/quit") || !strcmp(cmd, "/exit") || !strcmp(cmd, "/q")) {
155 endwin(); 153 endwin();
156 exit(0); 154 exit(0);
157 } 155 }
156
158 else if (!strncmp(cmd, "/status ", strlen("/status "))) { 157 else if (!strncmp(cmd, "/status ", strlen("/status "))) {
159 char* msg; 158 char *msg;
160 msg = strchr(cmd, ' '); 159 msg = strchr(cmd, ' ');
161 if(msg == NULL) { 160 if (msg == NULL) {
162 wprintw(ctx->history, "Invalid syntax.\n"); 161 wprintw(ctx->history, "Invalid syntax.\n");
163 return; 162 return;
164 } 163 }
@@ -166,10 +165,11 @@ void execute(ToxWindow* self, ChatContext* ctx, char* cmd)
166 m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1); 165 m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1);
167 wprintw(ctx->history, "Status set to: %s\n", msg); 166 wprintw(ctx->history, "Status set to: %s\n", msg);
168 } 167 }
168
169 else if (!strncmp(cmd, "/nick ", strlen("/nick "))) { 169 else if (!strncmp(cmd, "/nick ", strlen("/nick "))) {
170 char* nick; 170 char *nick;
171 nick = strchr(cmd, ' '); 171 nick = strchr(cmd, ' ');
172 if(nick == NULL) { 172 if (nick == NULL) {
173 wprintw(ctx->history, "Invalid syntax.\n"); 173 wprintw(ctx->history, "Invalid syntax.\n");
174 return; 174 return;
175 } 175 }
@@ -177,7 +177,8 @@ void execute(ToxWindow* self, ChatContext* ctx, char* cmd)
177 setname((uint8_t*) nick, strlen(nick)+1); 177 setname((uint8_t*) nick, strlen(nick)+1);
178 wprintw(ctx->history, "Nickname set to: %s\n", nick); 178 wprintw(ctx->history, "Nickname set to: %s\n", nick);
179 } 179 }
180 else if(!strcmp(cmd, "/myid")) { 180
181 else if (!strcmp(cmd, "/myid")) {
181 char id[32*2 + 1] = {0}; 182 char id[32*2 + 1] = {0};
182 int i; 183 int i;
183 for (i = 0; i < 32; i++) { 184 for (i = 0; i < 32; i++) {
@@ -187,58 +188,64 @@ void execute(ToxWindow* self, ChatContext* ctx, char* cmd)
187 } 188 }
188 wprintw(ctx->history, "Your ID: %s\n", id); 189 wprintw(ctx->history, "Your ID: %s\n", id);
189 } 190 }
191
192 else if (strcmp(ctx->line, "/close") == 0) {
193 active_window = 0; // Go to prompt screen
194 int f_num = ctx->friendnum;
195 delwin(ctx->linewin);
196 del_window(self, f_num);
197 }
198
190 else 199 else
191 wprintw(ctx->history, "Invalid command.\n"); 200 wprintw(ctx->history, "Invalid command.\n");
192} 201}
193 202
194static void chat_onDraw(ToxWindow* self) { 203static void chat_onDraw(ToxWindow *self)
204{
195 curs_set(1); 205 curs_set(1);
196 int x, y; 206 int x, y;
197 ChatContext* ctx = (ChatContext*) self->x; 207 ChatContext *ctx = (ChatContext*) self->x;
198
199 getmaxyx(self->window, y, x); 208 getmaxyx(self->window, y, x);
200
201 (void) x; 209 (void) x;
202 if(y < 3) 210 if (y < 3) return;
203 return;
204 211
205 wclear(ctx->linewin); 212 wclear(ctx->linewin);
206 mvwhline(ctx->linewin, 0, 0, '_', COLS); 213 mvwhline(ctx->linewin, 0, 0, '_', COLS);
207 mvwprintw(self->window, y-1, 0, "%s\n", ctx->line); 214 mvwprintw(self->window, y-1, 0, "%s\n", ctx->line);
208
209 wrefresh(self->window); 215 wrefresh(self->window);
210} 216}
211 217
212static void chat_onInit(ToxWindow* self) { 218static void chat_onInit(ToxWindow *self)
219{
213 int x, y; 220 int x, y;
214 ChatContext* ctx = (ChatContext*) self->x; 221 ChatContext *ctx = (ChatContext*) self->x;
215
216 getmaxyx(self->window, y, x); 222 getmaxyx(self->window, y, x);
217
218 ctx->history = subwin(self->window, y - 4, x, 0, 0); 223 ctx->history = subwin(self->window, y - 4, x, 0, 0);
219 scrollok(ctx->history, 1); 224 scrollok(ctx->history, 1);
220
221 ctx->linewin = subwin(self->window, 2, x, y - 3, 0); 225 ctx->linewin = subwin(self->window, 2, x, y - 3, 0);
226 print_help(ctx);
222} 227}
223 228
224void print_help(ChatContext* self) { 229void print_help(ChatContext *self)
230{
225 wattron(self->history, COLOR_PAIR(2) | A_BOLD); 231 wattron(self->history, COLOR_PAIR(2) | A_BOLD);
226 wprintw(self->history, "\nCommands:\n"); 232 wprintw(self->history, "Commands:\n");
227 wattroff(self->history, A_BOLD); 233 wattroff(self->history, A_BOLD);
228 234
229 wprintw(self->history, " /status <message> : Set your status\n"); 235 wprintw(self->history, " /status <message> : Set your status\n");
230 wprintw(self->history, " /nick <nickname> : Set your nickname\n"); 236 wprintw(self->history, " /nick <nickname> : Set your nickname\n");
231 wprintw(self->history, " /myid : Print your ID\n"); 237 wprintw(self->history, " /myid : Print your ID\n");
232 wprintw(self->history, " /clear : Clear the screen\n"); 238 wprintw(self->history, " /clear : Clear the screen\n");
239 wprintw(self->history, " /close : Close the current chat window\n");
233 wprintw(self->history, " /quit or /exit : Exit program\n"); 240 wprintw(self->history, " /quit or /exit : Exit program\n");
234 wprintw(self->history, " /help : Print this message again\n\n"); 241 wprintw(self->history, " /help : Print this message again\n\n");
235 242
236 wattroff(self->history, COLOR_PAIR(2)); 243 wattroff(self->history, COLOR_PAIR(2));
237} 244}
238 245
239ToxWindow new_chat(int friendnum) { 246ToxWindow new_chat(int friendnum)
247{
240 ToxWindow ret; 248 ToxWindow ret;
241
242 memset(&ret, 0, sizeof(ret)); 249 memset(&ret, 0, sizeof(ret));
243 250
244 ret.onKey = &chat_onKey; 251 ret.onKey = &chat_onKey;
@@ -254,9 +261,8 @@ ToxWindow new_chat(int friendnum) {
254 261
255 snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum); 262 snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum);
256 263
257 ChatContext* x = calloc(1, sizeof(ChatContext)); 264 ChatContext *x = calloc(1, sizeof(ChatContext));
258 x->friendnum = friendnum; 265 x->friendnum = friendnum;
259
260 ret.x = (void*) x; 266 ret.x = (void*) x;
261 return ret; 267 return ret;
262} 268}
diff --git a/testing/toxic/friendlist.c b/testing/toxic/friendlist.c
index 05651b0e..f03914e6 100644
--- a/testing/toxic/friendlist.c
+++ b/testing/toxic/friendlist.c
@@ -12,54 +12,59 @@
12 12
13#include "windows.h" 13#include "windows.h"
14 14
15extern int add_window(ToxWindow w); 15extern char WINDOW_STATUS[TOXWINDOWS_MAX_NUM];
16extern int focus_window(int num); 16extern int add_window(ToxWindow w, int n);
17extern ToxWindow new_chat(int friendnum); 17extern ToxWindow new_chat(int friendnum);
18 18
19#define MAX_FRIENDS_NUM 100 19extern int active_window;
20 20
21typedef struct { 21typedef struct {
22 uint8_t name[MAX_NAME_LENGTH]; 22 uint8_t name[MAX_NAME_LENGTH];
23 uint8_t status[MAX_USERSTATUS_LENGTH]; 23 uint8_t status[MAX_USERSTATUS_LENGTH];
24 int num; 24 int num;
25 int chatwin; 25 int chatwin;
26} friend_t; 26} friend_t;
27 27
28static friend_t friends[MAX_FRIENDS_NUM]; 28static friend_t friends[MAX_FRIENDS_NUM];
29static int num_friends = 0; 29static int num_friends = 0;
30static int num_selected = 0; 30static int num_selected = 0;
31 31
32 32void fix_name(uint8_t *name)
33void fix_name(uint8_t* name) { 33{
34 34 /* Remove all non alphanumeric characters */
35 // Remove all non alphanumeric characters. 35 uint8_t *p = name;
36 uint8_t* p = name; 36 uint8_t *q = name;
37 uint8_t* q = name;
38
39 while(*p != 0) { 37 while(*p != 0) {
40 if(isprint(*p)) { 38 if (isprint(*p))
41 *q++ = *p; 39 *q++ = *p;
42 }
43
44 p++; 40 p++;
45 } 41 }
46
47 *q = 0; 42 *q = 0;
48} 43}
49 44
50void friendlist_onMessage(ToxWindow* self, int num, uint8_t* str, uint16_t len) { 45void friendlist_onMessage(ToxWindow *self, int num, uint8_t *str, uint16_t len)
51 46{
52 if(num >= num_friends) 47 if (num >= num_friends)
53 return; 48 return;
54 49
55 if(friends[num].chatwin == -1) { 50 if (friends[num].chatwin == -1) {
56 friends[num].chatwin = add_window(new_chat(num)); 51 friends[num].chatwin = num;
52 int i;
53 /* Find first open slot to hold chat window */
54 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
55 if (WINDOW_STATUS[i] == -1) {
56 WINDOW_STATUS[i] = num;
57 add_window(new_chat(num), i);
58 active_window = i;
59 break;
60 }
61 }
57 } 62 }
58} 63}
59 64
60void friendlist_onNickChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) { 65void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t len)
61 66{
62 if(len >= MAX_NAME_LENGTH || num >= num_friends) 67 if (len >= MAX_NAME_LENGTH || num >= num_friends)
63 return; 68 return;
64 69
65 memcpy((char*) &friends[num].name, (char*) str, len); 70 memcpy((char*) &friends[num].name, (char*) str, len);
@@ -67,9 +72,9 @@ void friendlist_onNickChange(ToxWindow* self, int num, uint8_t* str, uint16_t le
67 fix_name(friends[num].name); 72 fix_name(friends[num].name);
68} 73}
69 74
70void friendlist_onStatusChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) { 75void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t len)
71 76{
72 if(len >= MAX_USERSTATUS_LENGTH || num >= num_friends) 77 if (len >= MAX_USERSTATUS_LENGTH || num >= num_friends)
73 return; 78 return;
74 79
75 memcpy((char*) &friends[num].status, (char*) str, len); 80 memcpy((char*) &friends[num].status, (char*) str, len);
@@ -77,48 +82,59 @@ void friendlist_onStatusChange(ToxWindow* self, int num, uint8_t* str, uint16_t
77 fix_name(friends[num].status); 82 fix_name(friends[num].status);
78} 83}
79 84
80int friendlist_onFriendAdded(int num) { 85int friendlist_onFriendAdded(int num)
81 86{
82 if(num_friends == MAX_FRIENDS_NUM) 87 if (num_friends == MAX_FRIENDS_NUM)
83 return -1; 88 return -1;
84 89
85 friends[num_friends].num = num; 90 friends[num_friends].num = num;
86 getname(num, friends[num_friends].name); 91 getname(num, friends[num_friends].name);
87 strcpy((char*) friends[num_friends].name, "unknown"); 92 strcpy((char*) friends[num_friends].name, "unknown");
88 strcpy((char*) friends[num_friends].status, "unknown"); 93 strcpy((char*) friends[num_friends].status, "unknown");
89 friends[num_friends].chatwin = -1; 94 friends[num_friends++].chatwin = -1;
90
91 num_friends++;
92 return 0; 95 return 0;
93} 96}
94 97
95static void friendlist_onKey(ToxWindow* self, int key) { 98static void friendlist_onKey(ToxWindow *self, int key)
96 99{
97 if(key == KEY_UP) { 100 if (key == KEY_UP) {
98 if(num_selected != 0) 101 if (--num_selected < 0)
99 num_selected--; 102 num_selected = num_friends-1;
100 } 103 }
101 else if(key == KEY_DOWN) { 104 else if (key == KEY_DOWN) {
102 if(num_friends != 0) 105 if (num_friends != 0)
103 num_selected = (num_selected+1) % num_friends; 106 num_selected = (num_selected+1) % num_friends;
104 } 107 }
105 else if(key == '\n') { 108 else if (key == '\n') {
106 109 /* Jump to chat window if already open */
107 if(friends[num_selected].chatwin != -1) 110 if (friends[num_selected].chatwin != -1) {
108 return; 111 int i;
109 112 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
110 friends[num_selected].chatwin = add_window(new_chat(num_selected)); 113 if (WINDOW_STATUS[i] == num_selected) {
111 focus_window(friends[num_selected].chatwin); 114 active_window = i;
115 break;
116 }
117 }
118 }else {
119 int i;
120 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
121 if (WINDOW_STATUS[i] == -1) {
122 WINDOW_STATUS[i] = num_selected;
123 friends[num_selected].chatwin = num_selected;
124 add_window(new_chat(num_selected), i);
125 active_window = i;
126 break;
127 }
128 }
129 }
112 } 130 }
113} 131}
114 132
115static void friendlist_onDraw(ToxWindow* self) { 133static void friendlist_onDraw(ToxWindow *self)
134{
116 curs_set(0); 135 curs_set(0);
117 size_t i;
118
119 werase(self->window); 136 werase(self->window);
120 137 if (num_friends == 0) {
121 if(num_friends == 0) {
122 wprintw(self->window, "Empty. Add some friends! :-)\n"); 138 wprintw(self->window, "Empty. Add some friends! :-)\n");
123 } 139 }
124 else { 140 else {
@@ -128,12 +144,11 @@ static void friendlist_onDraw(ToxWindow* self) {
128 } 144 }
129 145
130 wprintw(self->window, "\n"); 146 wprintw(self->window, "\n");
131 147 int i;
132 for(i=0; i<num_friends; i++) { 148 for (i = 0; i < num_friends; ++i) {
133 149 if (i == num_selected) wattron(self->window, COLOR_PAIR(3));
134 if(i == num_selected) wattron(self->window, COLOR_PAIR(3));
135 wprintw(self->window, " [#%d] ", friends[i].num); 150 wprintw(self->window, " [#%d] ", friends[i].num);
136 if(i == num_selected) wattroff(self->window, COLOR_PAIR(3)); 151 if (i == num_selected) wattroff(self->window, COLOR_PAIR(3));
137 152
138 attron(A_BOLD); 153 attron(A_BOLD);
139 wprintw(self->window, "%s ", friends[i].name); 154 wprintw(self->window, "%s ", friends[i].name);
@@ -141,18 +156,21 @@ static void friendlist_onDraw(ToxWindow* self) {
141 156
142 wprintw(self->window, "(%s)\n", friends[i].status); 157 wprintw(self->window, "(%s)\n", friends[i].status);
143 } 158 }
144
145 wrefresh(self->window); 159 wrefresh(self->window);
146} 160}
147 161
148static void friendlist_onInit(ToxWindow* self) { 162void disable_chatwin(int f_num)
149 163{
164 friends[f_num].chatwin = -1;
150} 165}
151 166
167static void friendlist_onInit(ToxWindow *self)
168{
169
170}
152 171
153ToxWindow new_friendlist() { 172ToxWindow new_friendlist() {
154 ToxWindow ret; 173 ToxWindow ret;
155
156 memset(&ret, 0, sizeof(ret)); 174 memset(&ret, 0, sizeof(ret));
157 175
158 ret.onKey = &friendlist_onKey; 176 ret.onKey = &friendlist_onKey;
@@ -161,7 +179,7 @@ ToxWindow new_friendlist() {
161 ret.onMessage = &friendlist_onMessage; 179 ret.onMessage = &friendlist_onMessage;
162 ret.onNickChange = &friendlist_onNickChange; 180 ret.onNickChange = &friendlist_onNickChange;
163 ret.onStatusChange = &friendlist_onStatusChange; 181 ret.onStatusChange = &friendlist_onStatusChange;
164 strcpy(ret.title, "[friends]");
165 182
183 strcpy(ret.title, "[friends]");
166 return ret; 184 return ret;
167} 185}
diff --git a/testing/toxic/main.c b/testing/toxic/main.c
index ee5e9f2a..1ba8b6c9 100644
--- a/testing/toxic/main.c
+++ b/testing/toxic/main.c
@@ -17,228 +17,238 @@ extern ToxWindow new_prompt();
17extern ToxWindow new_friendlist(); 17extern ToxWindow new_friendlist();
18 18
19extern int friendlist_onFriendAdded(int num); 19extern int friendlist_onFriendAdded(int num);
20extern void disable_chatwin(int f_num);
21extern int add_req(uint8_t *public_key); // XXX
20 22
21extern int add_req(uint8_t* public_key); // XXX 23/* Holds status of chat windows */
24char WINDOW_STATUS[MAX_WINDOW_SLOTS];
22 25
23#define TOXWINDOWS_MAX_NUM 32 26static ToxWindow windows[MAX_WINDOW_SLOTS];
24
25static ToxWindow windows[TOXWINDOWS_MAX_NUM];
26static int w_num;
27static int w_active;
28static ToxWindow* prompt; 27static ToxWindow* prompt;
29 28
30// CALLBACKS START 29int w_num;
31void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) { 30int active_window;
32 size_t i;
33 int n = add_req(public_key);
34 31
32/* CALLBACKS START */
33void on_request(uint8_t *public_key, uint8_t *data, uint16_t length)
34{
35 int n = add_req(public_key);
35 wprintw(prompt->window, "\nFriend request from:\n"); 36 wprintw(prompt->window, "\nFriend request from:\n");
36 37
37 for(i=0; i<32; i++) { 38 int i;
39 for (i = 0; i < 32; ++i) {
38 wprintw(prompt->window, "%02x", public_key[i] & 0xff); 40 wprintw(prompt->window, "%02x", public_key[i] & 0xff);
39 } 41 }
40 wprintw(prompt->window, "\n");
41 42
43 wprintw(prompt->window, "\n");
42 wprintw(prompt->window, "Use \"accept %d\" to accept it.\n", n); 44 wprintw(prompt->window, "Use \"accept %d\" to accept it.\n", n);
43 45 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
44 for(i=0; i<w_num; i++) { 46 if (windows[i].onFriendRequest != NULL)
45 if(windows[i].onFriendRequest != NULL)
46 windows[i].onFriendRequest(&windows[i], public_key, data, length); 47 windows[i].onFriendRequest(&windows[i], public_key, data, length);
47 } 48 }
48} 49}
49 50
50void on_message(int friendnumber, uint8_t* string, uint16_t length) { 51void on_message(int friendnumber, uint8_t *string, uint16_t length)
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 int i;
55 for(i=0; i<w_num; i++) { 55 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
56 if(windows[i].onMessage != NULL) 56 if (windows[i].onMessage != NULL)
57 windows[i].onMessage(&windows[i], friendnumber, string, length); 57 windows[i].onMessage(&windows[i], friendnumber, string, length);
58 } 58 }
59} 59}
60 60
61void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) { 61void on_nickchange(int friendnumber, uint8_t *string, uint16_t length)
62 size_t i; 62{
63
64 wprintw(prompt->window, "\n(nickchange) %d: %s!\n", friendnumber, string); 63 wprintw(prompt->window, "\n(nickchange) %d: %s!\n", friendnumber, string);
65 64 int i;
66 for(i=0; i<w_num; i++) { 65 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
67 if(windows[i].onNickChange != NULL) 66 if (windows[i].onNickChange != NULL)
68 windows[i].onNickChange(&windows[i], friendnumber, string, length); 67 windows[i].onNickChange(&windows[i], friendnumber, string, length);
69 } 68 }
70} 69}
71 70
72void on_statuschange(int friendnumber, USERSTATUS_KIND kind, uint8_t* string, uint16_t length) { 71void on_statuschange(int friendnumber, USERSTATUS_KIND kind, uint8_t *string, uint16_t length)
73 size_t i; 72{
74
75 wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); 73 wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string);
76 74 int i;
77 for(i=0; i<w_num; i++) { 75 for (i=0; i<MAX_WINDOW_SLOTS; ++i) {
78 if(windows[i].onStatusChange != NULL) 76 if (windows[i].onStatusChange != NULL)
79 windows[i].onStatusChange(&windows[i], friendnumber, string, length); 77 windows[i].onStatusChange(&windows[i], friendnumber, string, length);
80 } 78 }
81} 79}
82 80
83void on_friendadded(int friendnumber) { 81void on_friendadded(int friendnumber)
82{
84 friendlist_onFriendAdded(friendnumber); 83 friendlist_onFriendAdded(friendnumber);
85} 84}
86// CALLBACKS END 85/* CALLBACKS END */
87 86
88static void init_term() { 87static void init_term()
89 // Setup terminal. 88{
89 /* Setup terminal */
90 initscr(); 90 initscr();
91 cbreak(); 91 cbreak();
92 keypad(stdscr, 1); 92 keypad(stdscr, 1);
93 noecho(); 93 noecho();
94 timeout(100); 94 timeout(100);
95 95
96 if(has_colors()) { 96 if (has_colors()) {
97 start_color(); 97 start_color();
98 init_pair(1, COLOR_GREEN, COLOR_BLACK); 98 init_pair(1, COLOR_GREEN, COLOR_BLACK);
99 init_pair(2, COLOR_CYAN, COLOR_BLACK); 99 init_pair(2, COLOR_CYAN, COLOR_BLACK);
100 init_pair(3, COLOR_RED, COLOR_BLACK); 100 init_pair(3, COLOR_RED, COLOR_BLACK);
101 init_pair(4, COLOR_BLUE, COLOR_BLACK); 101 init_pair(4, COLOR_BLUE, COLOR_BLACK);
102 } 102 }
103
104 refresh(); 103 refresh();
105} 104}
106 105
107static void init_tox() { 106static void init_tox()
108 // Init core. 107{
108 /* Init core */
109 initMessenger(); 109 initMessenger();
110 110
111 // Callbacks. 111 /* Callbacks */
112 m_callback_friendrequest(on_request); 112 m_callback_friendrequest(on_request);
113 m_callback_friendmessage(on_message); 113 m_callback_friendmessage(on_message);
114 m_callback_namechange(on_nickchange); 114 m_callback_namechange(on_nickchange);
115 m_callback_userstatus(on_statuschange); 115 m_callback_userstatus(on_statuschange);
116} 116}
117 117
118int add_window(ToxWindow w) { 118void init_window_status()
119 if(w_num == TOXWINDOWS_MAX_NUM) 119{
120 /* Default window values decrement from -2 */
121 int i;
122 for (i = 0; i < N_DEFAULT_WINS; ++i)
123 WINDOW_STATUS[i] = -(i+2);
124
125 int j;
126 for (j = N_DEFAULT_WINS; j < MAX_WINDOW_SLOTS; j++)
127 WINDOW_STATUS[j] = -1;
128}
129
130int add_window(ToxWindow w, int n)
131{
132 if (w_num >= TOXWINDOWS_MAX_NUM)
120 return -1; 133 return -1;
121 134
122 if(LINES < 2) 135 if (LINES < 2)
123 return -1; 136 return -1;
124 137
125 w.window = newwin(LINES - 2, COLS, 0, 0); 138 w.window = newwin(LINES - 2, COLS, 0, 0);
126 139 if (w.window == NULL)
127 if(w.window == NULL)
128 return -1; 140 return -1;
129 141
130 windows[w_num++] = w; 142 windows[n] = w;
131 w.onInit(&w); 143 w.onInit(&w);
132 144 w_num++;
133 return w_num - 1; 145 return n;
134} 146}
135 147
136int focus_window(int num) { 148/* Deletes window w and cleans up */
137 if(num >= w_num || num < 0) 149void del_window(ToxWindow *w, int f_num)
138 return -1; 150{
139 151 delwin(w->window);
140 w_active = num; 152 int i;
141 return 0; 153 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
154 if (WINDOW_STATUS[i] == f_num) {
155 WINDOW_STATUS[i] = -1;
156 disable_chatwin(f_num);
157 break;
158 }
159 }
160 clear();
161 refresh();
142} 162}
143 163
144static void init_windows() { 164static void init_windows()
165{
145 w_num = 0; 166 w_num = 0;
146 w_active = 0; 167 int n_prompt = 0;
147 168 int n_friendslist = 1;
148 if(add_window(new_prompt()) == -1 || add_window(new_friendlist()) == -1) { 169 if (add_window(new_prompt(), n_prompt) == -1
170 || add_window(new_friendlist(), n_friendslist) == -1) {
149 fprintf(stderr, "add_window() failed.\n"); 171 fprintf(stderr, "add_window() failed.\n");
150
151 endwin(); 172 endwin();
152 exit(1); 173 exit(1);
153 } 174 }
154 175 prompt = &windows[n_prompt];
155 prompt = &windows[0];
156} 176}
157 177
158static void do_tox() { 178static void do_tox()
179{
159 static bool dht_on = false; 180 static bool dht_on = false;
160 181 if (!dht_on && DHT_isconnected()) {
161 if(!dht_on && DHT_isconnected()) {
162 dht_on = true; 182 dht_on = true;
163 wprintw(prompt->window, "\nDHT connected!\n"); 183 wprintw(prompt->window, "\nDHT connected!\n");
164 } 184 }
165 else if(dht_on && !DHT_isconnected()) { 185 else if (dht_on && !DHT_isconnected()) {
166 dht_on = false; 186 dht_on = false;
167 wprintw(prompt->window, "\nDHT disconnected!\n"); 187 wprintw(prompt->window, "\nDHT disconnected!\n");
168 } 188 }
169
170 doMessenger(); 189 doMessenger();
171} 190}
172 191
173static void load_data(char *path) { 192static void load_data(char *path)
174 FILE* fd; 193{
194 FILE *fd;
175 size_t len; 195 size_t len;
176 uint8_t* buf; 196 uint8_t *buf;
177 197
178 if((fd = fopen(path, "r")) != NULL) { 198 if ((fd = fopen(path, "r")) != NULL) {
179 fseek(fd, 0, SEEK_END); 199 fseek(fd, 0, SEEK_END);
180 len = ftell(fd); 200 len = ftell(fd);
181 fseek(fd, 0, SEEK_SET); 201 fseek(fd, 0, SEEK_SET);
182 202
183 buf = malloc(len); 203 buf = malloc(len);
184 204 if (buf == NULL) {
185 if(buf == NULL) {
186 fprintf(stderr, "malloc() failed.\n"); 205 fprintf(stderr, "malloc() failed.\n");
187
188 fclose(fd); 206 fclose(fd);
189 endwin(); 207 endwin();
190 exit(1); 208 exit(1);
191 } 209 }
192 210 if (fread(buf, len, 1, fd) != 1){
193 if(fread(buf, len, 1, fd) != 1){
194 fprintf(stderr, "fread() failed.\n"); 211 fprintf(stderr, "fread() failed.\n");
195
196 free(buf); 212 free(buf);
197 fclose(fd); 213 fclose(fd);
198 endwin(); 214 endwin();
199 exit(1); 215 exit(1);
200 } 216 }
201
202 Messenger_load(buf, len); 217 Messenger_load(buf, len);
203 } 218 }
204 else { 219 else {
205 len = Messenger_size(); 220 len = Messenger_size();
206 buf = malloc(len); 221 buf = malloc(len);
207 222 if (buf == NULL) {
208 if(buf == NULL) {
209 fprintf(stderr, "malloc() failed.\n"); 223 fprintf(stderr, "malloc() failed.\n");
210 endwin(); 224 endwin();
211 exit(1); 225 exit(1);
212 } 226 }
213
214 Messenger_save(buf); 227 Messenger_save(buf);
215 228
216 fd = fopen(path, "w"); 229 fd = fopen(path, "w");
217 if(fd == NULL) { 230 if (fd == NULL) {
218 fprintf(stderr, "fopen() failed.\n"); 231 fprintf(stderr, "fopen() failed.\n");
219
220 free(buf); 232 free(buf);
221 endwin(); 233 endwin();
222 exit(1); 234 exit(1);
223 } 235 }
224 236
225 if(fwrite(buf, len, 1, fd) != 1){ 237 if (fwrite(buf, len, 1, fd) != 1){
226 fprintf(stderr, "fwrite() failed.\n"); 238 fprintf(stderr, "fwrite() failed.\n");
227
228 free(buf); 239 free(buf);
229 fclose(fd); 240 fclose(fd);
230 endwin(); 241 endwin();
231 exit(1); 242 exit(1);
232 } 243 }
233 } 244 }
234
235 free(buf); 245 free(buf);
236 fclose(fd); 246 fclose(fd);
237} 247}
238 248
239static void draw_bar() { 249static void draw_bar()
250{
240 static int odd = 0; 251 static int odd = 0;
241 size_t i;
242 252
243 attron(COLOR_PAIR(4)); 253 attron(COLOR_PAIR(4));
244 mvhline(LINES - 2, 0, '_', COLS); 254 mvhline(LINES - 2, 0, '_', COLS);
@@ -250,95 +260,124 @@ static void draw_bar() {
250 printw(" TOXIC 1.0 |"); 260 printw(" TOXIC 1.0 |");
251 attroff(COLOR_PAIR(4) | A_BOLD); 261 attroff(COLOR_PAIR(4) | A_BOLD);
252 262
253 for(i=0; i<w_num; i++) { 263 int i;
254 if(i == w_active) { 264 for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) {
255 attron(A_BOLD); 265 if (WINDOW_STATUS[i] != -1) {
256 } 266 if (i == active_window)
257 267 attron(A_BOLD);
258 odd = (odd+1) % 10; 268
259 269 odd = (odd+1) % 10;
260 if(windows[i].blink && (odd < 5)) { 270 if (windows[i].blink && (odd < 5)) {
261 attron(COLOR_PAIR(3)); 271 attron(COLOR_PAIR(3));
262 } 272 }
263 273
264 printw(" %s", windows[i].title); 274 printw(" %s", windows[i].title);
265 275 if (windows[i].blink && (odd < 5)) {
266 if(windows[i].blink && (odd < 5)) { 276 attron(COLOR_PAIR(3));
267 attron(COLOR_PAIR(3)); 277 }
268 } 278 if (i == active_window) {
269 279 attroff(A_BOLD);
270 if(i == w_active) { 280 }
271 attroff(A_BOLD);
272 } 281 }
273 } 282 }
274
275 refresh(); 283 refresh();
276} 284}
277 285
278void prepare_window(WINDOW* w) { 286void prepare_window(WINDOW *w)
287{
279 mvwin(w, 0, 0); 288 mvwin(w, 0, 0);
280 wresize(w, LINES-2, COLS); 289 wresize(w, LINES-2, COLS);
281} 290}
282 291
283int main(int argc, char* argv[]) { 292/* Shows next window when tab or back-tab is pressed */
293void set_active_window(int ch)
294{
295 int f_inf = 0;
296 int max = MAX_WINDOW_SLOTS-1;
297 if (ch == '\t') {
298 int i = (active_window + 1) % max;
299 while (true) {
300 if (WINDOW_STATUS[i] != -1) {
301 active_window = i;
302 return;
303 }
304 i = (i + 1) % max;
305 if (f_inf++ > max) { // infinite loop check
306 endwin();
307 clear();
308 exit(2);
309 }
310 }
311 }else {
312 int i = active_window - 1;
313 if (i < 0) i = max;
314 while (true) {
315 if (WINDOW_STATUS[i] != -1) {
316 active_window = i;
317 return;
318 }
319 if (--i < 0) i = max;
320 if (f_inf++ > max) {
321 endwin();
322 clear();
323 exit(2);
324 }
325 }
326 }
327}
328
329int main(int argc, char *argv[])
330{
284 int ch; 331 int ch;
285 int i = 0;
286 int f_flag = 0; 332 int f_flag = 0;
287 char *filename = "data"; 333 char *filename = "data";
288 ToxWindow* a; 334 ToxWindow* a;
289 335
290 for(i = 0; i < argc; i++) { 336 int i = 0;
291 if (argv[i] == NULL){ 337 for (i = 0; i < argc; ++i) {
292 break; 338 if (argv[i] == NULL)
293 } else if(argv[i][0] == '-') { 339 break;
294 if(argv[i][1] == 'f') { 340 else if (argv[i][0] == '-') {
295 if(argv[i + 1] != NULL) 341 if (argv[i][1] == 'f') {
296 filename = argv[i + 1]; 342 if (argv[i + 1] != NULL)
297 else { 343 filename = argv[i + 1];
298 f_flag = -1; 344 else
299 } 345 f_flag = -1;
300 } 346 }
301 }
302 } 347 }
348 }
303 349
304 init_term(); 350 init_term();
305 init_tox(); 351 init_tox();
306 load_data(filename); 352 load_data(filename);
307 init_windows(); 353 init_windows();
354 init_window_status();
308 355
309 if(f_flag == -1) { 356 if (f_flag == -1) {
310 attron(COLOR_PAIR(3) | A_BOLD); 357 attron(COLOR_PAIR(3) | A_BOLD);
311 wprintw(prompt->window, "You passed '-f' without giving an argument!\n" 358 wprintw(prompt->window, "You passed '-f' without giving an argument!\n"
312 "defaulting to 'data' for a keyfile...\n"); 359 "defaulting to 'data' for a keyfile...\n");
313 attroff(COLOR_PAIR(3) | A_BOLD); 360 attroff(COLOR_PAIR(3) | A_BOLD);
314 } 361 }
315 362
316
317 while(true) { 363 while(true) {
318 // Update tox. 364 /* Update tox */
319 do_tox(); 365 do_tox();
320 366
321 // Draw. 367 /* Draw */
322 a = &windows[w_active]; 368 a = &windows[active_window];
323 prepare_window(a->window); 369 prepare_window(a->window);
324 a->blink = false; 370 a->blink = false;
325 draw_bar(); 371 draw_bar();
326 a->onDraw(a); 372 a->onDraw(a);
327 373
328 // Handle input. 374 /* Handle input */
329 ch = getch(); 375 ch = getch();
330 if(ch == '\t') { 376 if (ch == '\t' || ch == KEY_BTAB)
331 w_active = (w_active + 1) % w_num; 377 set_active_window(ch);
332 } 378 else if (ch != ERR) {
333 else if(ch == KEY_BTAB) {
334 w_active = (w_active + w_num - 1) % w_num;
335 }
336 else if(ch != ERR) {
337 a->onKey(a, ch); 379 a->onKey(a, ch);
338 } 380 }
339
340 } 381 }
341
342 return 0; 382 return 0;
343} 383}
344
diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c
index 16750c5d..89c87d8f 100644
--- a/testing/toxic/prompt.c
+++ b/testing/toxic/prompt.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Toxic -- Tox Curses Client 2* Toxic -- Tox Curses Client
3 */ 3*/
4 4
5#include <stdlib.h> 5#include <stdlib.h>
6#include <string.h> 6#include <string.h>
@@ -16,73 +16,78 @@ uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX
16uint8_t num_requests=0; // XXX 16uint8_t num_requests=0; // XXX
17 17
18extern void on_friendadded(int friendnumber); 18extern void on_friendadded(int friendnumber);
19static void print_usage(ToxWindow* self); 19static void print_usage(ToxWindow *self);
20static char prompt_buf[256] = {0};
21static int prompt_buf_pos = 0;
20 22
21// XXX: 23// XXX:
22int add_req(uint8_t* public_key) { 24int add_req(uint8_t *public_key)
25{
23 memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE); 26 memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE);
24 ++num_requests; 27 ++num_requests;
25
26 return num_requests-1; 28 return num_requests-1;
27} 29}
28 30
29// XXX: FIX 31// XXX: FIX
30unsigned char * hex_string_to_bin(char hex_string[]) 32unsigned char *hex_string_to_bin(char hex_string[])
31{ 33{
32 size_t len = strlen(hex_string); 34 size_t len = strlen(hex_string);
33 unsigned char *val = malloc(len); 35 unsigned char *val = malloc(len);
34 char *pos = hex_string; 36 char *pos = hex_string;
35 int i; 37 int i;
36 for(i = 0; i < len; ++i, pos+=2) 38 for (i = 0; i < len; ++i, pos+=2)
37 sscanf(pos,"%2hhx",&val[i]); 39 sscanf(pos,"%2hhx",&val[i]);
38 return val; 40 return val;
39} 41}
40 42
41static char prompt_buf[256] = {0}; 43static void execute(ToxWindow *self, char *u_cmd)
42static int prompt_buf_pos=0; 44{
43 45 int newlines = 0;
44static void execute(ToxWindow* self, char* cmd) { 46 char cmd[256] = {0};
47 int i;
48 for (i = 0; i < strlen(prompt_buf); ++i) {
49 if (u_cmd[i] == '\n')
50 ++newlines;
51 else
52 cmd[i - newlines] = u_cmd[i];
53 }
45 54
46 if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) { 55 if (!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) {
47 endwin(); 56 endwin();
48 exit(0); 57 exit(0);
49 } 58 }
50 else if(!strncmp(cmd, "connect ", strlen("connect "))) {
51 char* ip;
52 char* port;
53 char* key;
54 IP_Port dht;
55 59
56 ip = strchr(cmd, ' '); 60 else if (!strncmp(cmd, "connect ", strlen("connect "))) {
57 if(ip == NULL) { 61 IP_Port dht;
62 char *ip = strchr(cmd, ' ');
63 if (ip == NULL) {
58 wprintw(self->window, "Invalid syntax.\n"); 64 wprintw(self->window, "Invalid syntax.\n");
59 return; 65 return;
60 } 66 }
61 ip++; 67 ip++;
62 68
63 port = strchr(ip, ' '); 69 char *port = strchr(ip, ' ');
64 if(port == NULL) { 70 if (port == NULL) {
65 wprintw(self->window, "Invalid syntax.\n"); 71 wprintw(self->window, "Invalid syntax.\n");
66 return; 72 return;
67 } 73 }
68 port[0] = 0; 74 port[0] = 0;
69 port++; 75 port++;
70 76
71 key = strchr(port, ' '); 77 char *key = strchr(port, ' ');
72 if(key == NULL) { 78 if (key == NULL) {
73 wprintw(self->window, "Invalid syntax.\n"); 79 wprintw(self->window, "Invalid syntax.\n");
74 return; 80 return;
75 } 81 }
76 key[0] = 0; 82 key[0] = 0;
77 key++; 83 key++;
78 84
79 if(atoi(port) == 0) { 85 if (atoi(port) == 0) {
80 wprintw(self->window, "Invalid syntax.\n"); 86 wprintw(self->window, "Invalid syntax.\n");
81 return; 87 return;
82 } 88 }
83 89
84 dht.port = htons(atoi(port)); 90 dht.port = htons(atoi(port));
85
86 uint32_t resolved_address = resolve_addr(ip); 91 uint32_t resolved_address = resolve_addr(ip);
87 if (resolved_address == 0) { 92 if (resolved_address == 0) {
88 return; 93 return;
@@ -93,49 +98,39 @@ static void execute(ToxWindow* self, char* cmd) {
93 DHT_bootstrap(dht, binary_string); 98 DHT_bootstrap(dht, binary_string);
94 free(binary_string); 99 free(binary_string);
95 } 100 }
96 else if(!strncmp(cmd, "add ", strlen("add "))) { 101
102 else if (!strncmp(cmd, "add ", strlen("add "))) {
97 uint8_t id_bin[32]; 103 uint8_t id_bin[32];
98 size_t i;
99 char xx[3]; 104 char xx[3];
100 uint32_t x; 105 uint32_t x;
101 106 char *id = strchr(cmd, ' ');
102 char* id; 107 if (id == NULL) {
103 char* msg;
104 int num;
105
106 id = strchr(cmd, ' ');
107 if(id == NULL) {
108 wprintw(self->window, "Invalid syntax.\n"); 108 wprintw(self->window, "Invalid syntax.\n");
109 return; 109 return;
110 } 110 }
111 id++; 111 id++;
112 112 char *msg = strchr(id, ' ');
113 msg = strchr(id, ' '); 113 if (msg != NULL) {
114 if(msg != NULL) {
115 msg[0] = 0; 114 msg[0] = 0;
116 msg++; 115 msg++;
117 } 116 }
118 else msg = ""; 117 else msg = "";
119 118 if (strlen(id) != 2*32) {
120 if(strlen(id) != 2*32) {
121 wprintw(self->window, "Invalid ID length.\n"); 119 wprintw(self->window, "Invalid ID length.\n");
122 return; 120 return;
123 } 121 }
124 122 int i;
125 for(i=0; i<32; i++) { 123 for (i = 0; i < 32; ++i) {
126 xx[0] = id[2*i]; 124 xx[0] = id[2*i];
127 xx[1] = id[2*i+1]; 125 xx[1] = id[2*i+1];
128 xx[2] = '\0'; 126 xx[2] = '\0';
129 127 if (sscanf(xx, "%02x", &x) != 1) {
130 if(sscanf(xx, "%02x", &x) != 1) {
131 wprintw(self->window, "Invalid ID.\n"); 128 wprintw(self->window, "Invalid ID.\n");
132 return; 129 return;
133 } 130 }
134
135 id_bin[i] = x; 131 id_bin[i] = x;
136 } 132 }
137 133 int num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1);
138 num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1);
139 switch (num) { 134 switch (num) {
140 case -1: 135 case -1:
141 wprintw(self->window, "Message is too long.\n"); 136 wprintw(self->window, "Message is too long.\n");
@@ -158,158 +153,157 @@ static void execute(ToxWindow* self, char* cmd) {
158 break; 153 break;
159 } 154 }
160 } 155 }
161 else if(!strcmp(cmd, "clear")) { 156
162 wclear(self->window); 157 else if (!strcmp(cmd, "clear")) {
158 wclear(self->window);
163 } 159 }
164 else if(!strcmp(cmd, "help")) { 160
165 print_usage(self); 161 else if (!strcmp(cmd, "help")) {
162 wclear(self->window);
163 print_usage(self);
166 } 164 }
167 else if(!strncmp(cmd, "status ", strlen("status "))) {
168 char* msg;
169 165
170 msg = strchr(cmd, ' '); 166 else if (!strncmp(cmd, "status ", strlen("status "))) {
171 if(msg == NULL) { 167 char *msg = strchr(cmd, ' ');
168 if (msg == NULL) {
172 wprintw(self->window, "Invalid syntax.\n"); 169 wprintw(self->window, "Invalid syntax.\n");
173 return; 170 return;
174 } 171 }
175 msg++; 172 msg++;
176
177 m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1); 173 m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1);
178 wprintw(self->window, "Status set to: %s\n", msg); 174 wprintw(self->window, "Status set to: %s\n", msg);
179 } 175 }
180 else if(!strncmp(cmd, "nick ", strlen("nick "))) {
181 char* nick;
182 176
183 nick = strchr(cmd, ' '); 177 else if (!strncmp(cmd, "nick ", strlen("nick "))) {
184 if(nick == NULL) { 178 char *nick = strchr(cmd, ' ');
179 if (nick == NULL) {
185 wprintw(self->window, "Invalid syntax.\n"); 180 wprintw(self->window, "Invalid syntax.\n");
186 return; 181 return;
187 } 182 }
188 nick++; 183 nick++;
189
190 setname((uint8_t*) nick, strlen(nick)+1); 184 setname((uint8_t*) nick, strlen(nick)+1);
191 wprintw(self->window, "Nickname set to: %s\n", nick); 185 wprintw(self->window, "Nickname set to: %s\n", nick);
192 } 186 }
193 else if(!strcmp(cmd, "myid")) { 187
188 else if (!strcmp(cmd, "myid")) {
194 char id[32*2 + 1] = {0}; 189 char id[32*2 + 1] = {0};
195 size_t i; 190 size_t i;
196 191 for (i = 0; i < 32; ++i) {
197 for(i=0; i<32; i++) {
198 char xx[3]; 192 char xx[3];
199 snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); 193 snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff);
200 strcat(id, xx); 194 strcat(id, xx);
201 } 195 }
202
203 wprintw(self->window, "Your ID: %s\n", id); 196 wprintw(self->window, "Your ID: %s\n", id);
204 } 197 }
205 else if(!strncmp(cmd, "accept ", strlen("accept "))) {
206 char* id;
207 int num;
208 198
209 id = strchr(cmd, ' '); 199 else if (!strncmp(cmd, "accept ", strlen("accept "))) {
210 if(id == NULL) { 200 char *id = strchr(cmd, ' ');
201 if (id == NULL) {
211 wprintw(self->window, "Invalid syntax.\n"); 202 wprintw(self->window, "Invalid syntax.\n");
212 return; 203 return;
213 } 204 }
214 id++; 205 id++;
215 206
216 num = atoi(id); 207 int num = atoi(id);
217 if(num >= num_requests) { 208 if (num >= num_requests) {
218 wprintw(self->window, "Invalid syntax.\n"); 209 wprintw(self->window, "Invalid syntax.\n");
219 return; 210 return;
220 } 211 }
221 212
222 num = m_addfriend_norequest(pending_requests[num]); 213 num = m_addfriend_norequest(pending_requests[num]);
223 214 if (num == -1)
224 if(num == -1) {
225 wprintw(self->window, "Failed to add friend.\n"); 215 wprintw(self->window, "Failed to add friend.\n");
226 }
227 else { 216 else {
228 wprintw(self->window, "Friend accepted as: %d.\n", num); 217 wprintw(self->window, "Friend accepted as: %d.\n", num);
229 on_friendadded(num); 218 on_friendadded(num);
230 } 219 }
231 } 220 }
232 else if(!strncmp(cmd, "msg ", strlen("msg "))) {
233 char* id;
234 char* msg;
235 221
236 id = strchr(cmd, ' '); 222 else if (!strncmp(cmd, "msg ", strlen("msg "))) {
237 223 char *id = strchr(cmd, ' ');
238 if(id == NULL) { 224 if (id == NULL) {
239 wprintw(self->window, "Invalid syntax.\n"); 225 wprintw(self->window, "Invalid syntax.\n");
240 return; 226 return;
241 } 227 }
242 id++; 228 char *msg = strchr(++id, ' ');
243 229 if (msg == NULL) {
244 msg = strchr(id, ' ');
245 if(msg == NULL) {
246 wprintw(self->window, "Invalid syntax.\n"); 230 wprintw(self->window, "Invalid syntax.\n");
247 return; 231 return;
248 } 232 }
249 msg[0] = 0; 233 msg[0] = 0;
250 msg++; 234 msg++;
251 235 if (m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) < 0)
252 if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) < 0) {
253 wprintw(self->window, "Error occurred while sending message.\n"); 236 wprintw(self->window, "Error occurred while sending message.\n");
254 } 237 else
255 else {
256 wprintw(self->window, "Message successfully sent.\n"); 238 wprintw(self->window, "Message successfully sent.\n");
257 }
258 } 239 }
259 240 else
260 else {
261 wprintw(self->window, "Invalid command.\n"); 241 wprintw(self->window, "Invalid command.\n");
262 }
263} 242}
264 243
265static void prompt_onKey(ToxWindow* self, int key) { 244static void prompt_onKey(ToxWindow *self, int key)
266 // PRINTABLE characters: Add to line. 245{
267 if(isprint(key)) { 246 /* Add printable characters to line */
268 if(prompt_buf_pos == (sizeof(prompt_buf) - 1)) { 247 if (isprint(key)) {
269 return; 248 if (prompt_buf_pos == (sizeof(prompt_buf) - 1)) {
249 wprintw(self->window, "\nToo Long.\n");
250 prompt_buf_pos = 0;
251 prompt_buf[0] = 0;
252 }
253 else if (!(prompt_buf_pos == 0) && (prompt_buf_pos < COLS)
254 && (prompt_buf_pos % (COLS - 3) == 0)) {
255 prompt_buf[prompt_buf_pos++] = '\n';
256 }
257 else if (!(prompt_buf_pos == 0) && (prompt_buf_pos > COLS)
258 && ((prompt_buf_pos - (COLS - 3)) % (COLS) == 0)) {
259 prompt_buf[prompt_buf_pos++] = '\n';
270 } 260 }
271 prompt_buf[prompt_buf_pos++] = key; 261 prompt_buf[prompt_buf_pos++] = key;
272 prompt_buf[prompt_buf_pos] = 0; 262 prompt_buf[prompt_buf_pos] = 0;
273 } 263 }
274 264
275 // RETURN key: execute command. 265 /* RETURN key: execute command */
276 else if(key == '\n') { 266 else if (key == '\n') {
277 wprintw(self->window, "\n"); 267 wprintw(self->window, "\n");
278 execute(self, prompt_buf); 268 execute(self, prompt_buf);
279 prompt_buf_pos = 0; 269 prompt_buf_pos = 0;
280 prompt_buf[0] = 0; 270 prompt_buf[0] = 0;
281 } 271 }
282 272
283 // BACKSPACE key: Remove one character from line. 273 /* BACKSPACE key: Remove one character from line */
284 else if(key == 0x107 || key == 0x8 || key == 0x7f) { 274 else if (key == 0x107 || key == 0x8 || key == 0x7f) {
285 if(prompt_buf_pos != 0) { 275 if (prompt_buf_pos != 0) {
286 prompt_buf[--prompt_buf_pos] = 0; 276 prompt_buf[--prompt_buf_pos] = 0;
287 } 277 }
288 } 278 }
289} 279}
290 280
291static void prompt_onDraw(ToxWindow* self) { 281static void prompt_onDraw(ToxWindow *self)
282{
292 curs_set(1); 283 curs_set(1);
293 int x, y; 284 int x, y;
294
295 getyx(self->window, y, x); 285 getyx(self->window, y, x);
296 (void) x; 286 (void) x;
287 int i;
288 for (i = 0; i < (strlen(prompt_buf)); ++i) {
289 if ((prompt_buf[i] == '\n') && (y != 0))
290 --y;
291 }
297 292
298 wattron(self->window, COLOR_PAIR(1)); 293 wattron(self->window, COLOR_PAIR(1));
299 mvwprintw(self->window, y, 0, "# "); 294 mvwprintw(self->window, y, 0, "# ");
300 wattroff(self->window, COLOR_PAIR(1)); 295 wattroff(self->window, COLOR_PAIR(1));
301
302 mvwprintw(self->window, y, 2, "%s", prompt_buf); 296 mvwprintw(self->window, y, 2, "%s", prompt_buf);
303 wclrtoeol(self->window); 297 wclrtoeol(self->window);
304
305 wrefresh(self->window); 298 wrefresh(self->window);
306} 299}
307 300
308static void print_usage(ToxWindow* self) { 301static void print_usage(ToxWindow *self)
302{
309 wattron(self->window, COLOR_PAIR(2) | A_BOLD); 303 wattron(self->window, COLOR_PAIR(2) | A_BOLD);
310 wprintw(self->window, "Commands:\n"); 304 wprintw(self->window, "Commands:\n");
311 wattroff(self->window, A_BOLD); 305 wattroff(self->window, A_BOLD);
312 306
313 wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n"); 307 wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n");
314 wprintw(self->window, " add <id> <message> : Add friend\n"); 308 wprintw(self->window, " add <id> <message> : Add friend\n");
315 wprintw(self->window, " status <message> : Set your status\n"); 309 wprintw(self->window, " status <message> : Set your status\n");
@@ -318,8 +312,8 @@ static void print_usage(ToxWindow* self) {
318 wprintw(self->window, " myid : Print your ID\n"); 312 wprintw(self->window, " myid : Print your ID\n");
319 wprintw(self->window, " quit/exit : Exit program\n"); 313 wprintw(self->window, " quit/exit : Exit program\n");
320 wprintw(self->window, " help : Print this message again\n"); 314 wprintw(self->window, " help : Print this message again\n");
321 wprintw(self->window, " clear : Clear this window\n"); 315 wprintw(self->window, " clear : Clear this window\n");
322 316
323 wattron(self->window, A_BOLD); 317 wattron(self->window, A_BOLD);
324 wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); 318 wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n");
325 wattroff(self->window, A_BOLD); 319 wattroff(self->window, A_BOLD);
@@ -327,22 +321,20 @@ static void print_usage(ToxWindow* self) {
327 wattroff(self->window, COLOR_PAIR(2)); 321 wattroff(self->window, COLOR_PAIR(2));
328} 322}
329 323
330static void prompt_onInit(ToxWindow* self) { 324static void prompt_onInit(ToxWindow *self)
325{
331 scrollok(self->window, 1); 326 scrollok(self->window, 1);
332
333 print_usage(self); 327 print_usage(self);
334 wclrtoeol(self->window); 328 wclrtoeol(self->window);
335} 329}
336 330
337ToxWindow new_prompt() { 331ToxWindow new_prompt()
332{
338 ToxWindow ret; 333 ToxWindow ret;
339
340 memset(&ret, 0, sizeof(ret)); 334 memset(&ret, 0, sizeof(ret));
341
342 ret.onKey = &prompt_onKey; 335 ret.onKey = &prompt_onKey;
343 ret.onDraw = &prompt_onDraw; 336 ret.onDraw = &prompt_onDraw;
344 ret.onInit = &prompt_onInit; 337 ret.onInit = &prompt_onInit;
345 strcpy(ret.title, "[prompt]"); 338 strcpy(ret.title, "[prompt]");
346
347 return ret; 339 return ret;
348} 340}
diff --git a/testing/toxic/windows.h b/testing/toxic/windows.h
index dde1430f..cb45614d 100644
--- a/testing/toxic/windows.h
+++ b/testing/toxic/windows.h
@@ -3,6 +3,14 @@
3 */ 3 */
4 4
5#include <stdbool.h> 5#include <stdbool.h>
6#define TOXWINDOWS_MAX_NUM 32
7#define MAX_FRIENDS_NUM 100
8
9/* number of permanent default windows */
10#define N_DEFAULT_WINS 2
11
12/* maximum window slots for WINDOW_STATUS array */
13#define MAX_WINDOW_SLOTS N_DEFAULT_WINS+MAX_FRIENDS_NUM
6 14
7typedef struct ToxWindow_ ToxWindow; 15typedef struct ToxWindow_ ToxWindow;
8 16