summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Rose <michael_rose@gmx.de>2013-08-15 11:24:40 +0200
committerMichael Rose <michael_rose@gmx.de>2013-08-15 11:24:40 +0200
commit52d3194e8714a5041503ba953cbe5dfce0cb2e9b (patch)
treedb11ae02180ffdeb3d40a2d8e002fc56248f5903
parent5c7245fecdbb83cd6833e0fad3ea5a035d37a1e4 (diff)
parentbf6c04b2cafe0a132aa54c6134217a0f4369a054 (diff)
Merge official
-rw-r--r--README.md2
-rw-r--r--auto_tests/crypto_test.c38
-rw-r--r--core/DHT.c74
-rw-r--r--core/DHT.h13
-rw-r--r--core/Messenger.c39
-rw-r--r--core/Messenger.h12
-rw-r--r--core/friend_requests.c44
-rw-r--r--core/net_crypto.c127
-rw-r--r--core/net_crypto.h10
-rw-r--r--other/tox.pngbin0 -> 17922 bytes
-rw-r--r--testing/DHT_test.c4
-rw-r--r--testing/nTox.c21
-rw-r--r--testing/toxic/CMakeLists.txt2
-rw-r--r--testing/toxic/chat.c9
-rw-r--r--testing/toxic/chat.h6
-rw-r--r--testing/toxic/dhtstatus.c89
-rw-r--r--testing/toxic/dhtstatus.h8
-rw-r--r--testing/toxic/friendlist.c18
-rw-r--r--testing/toxic/friendlist.h12
-rw-r--r--testing/toxic/main.c414
-rw-r--r--testing/toxic/prompt.c23
-rw-r--r--testing/toxic/prompt.h14
-rw-r--r--testing/toxic/windows.c239
-rw-r--r--testing/toxic/windows.h25
24 files changed, 682 insertions, 561 deletions
diff --git a/README.md b/README.md
index 81836b4f..d4106910 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
1![Project Tox](https://rbt.asia/boards/g/img/0352/79/1373823047559.png "Project Tox") 1![Project Tox](https://raw.github.com/irungentoo/ProjectTox-Core/master/other/tox.png "Project Tox")
2Project Tox, _also known as Tox_, is a FOSS (Free and Open Source Software) instant messaging application aimed to replace Skype.<br /> 2Project Tox, _also known as Tox_, is a FOSS (Free and Open Source Software) instant messaging application aimed to replace Skype.<br />
3 3
4With the rise of governmental monitoring programs, Tox aims to be an easy to use, all-in-one communication platform (including audio, and videochats in the future) that ensures their users full privacy and secure message delivery.<br /> <br /> 4With the rise of governmental monitoring programs, Tox aims to be an easy to use, all-in-one communication platform (including audio, and videochats in the future) that ensures their users full privacy and secure message delivery.<br /> <br />
diff --git a/auto_tests/crypto_test.c b/auto_tests/crypto_test.c
index 9ac81349..8b5397e4 100644
--- a/auto_tests/crypto_test.c
+++ b/auto_tests/crypto_test.c
@@ -197,6 +197,43 @@ START_TEST(test_endtoend)
197} 197}
198END_TEST 198END_TEST
199 199
200START_TEST(test_large_data)
201{
202 unsigned char k[crypto_box_BEFORENMBYTES];
203
204 unsigned char n[crypto_box_NONCEBYTES];
205
206 unsigned char m1[MAX_DATA_SIZE - ENCRYPTION_PADDING];
207 unsigned char c1[sizeof(m1) + ENCRYPTION_PADDING];
208 unsigned char m1prime[sizeof(m1)];
209
210 unsigned char m2[MAX_DATA_SIZE];
211 unsigned char c2[sizeof(m2) + ENCRYPTION_PADDING];
212
213 int c1len, c2len;
214 int m1plen;
215
216 //Generate random messages
217 rand_bytes(m1, sizeof(m1));
218 rand_bytes(m2, sizeof(m2));
219 rand_bytes(n, crypto_box_NONCEBYTES);
220
221 //Generate key
222 rand_bytes(k, crypto_box_BEFORENMBYTES);
223
224 c1len = encrypt_data_fast(k, n, m1, sizeof(m1), c1);
225 c2len = encrypt_data_fast(k, n, m2, sizeof(m2), c2);
226
227 ck_assert_msg(c1len == sizeof(m1) + ENCRYPTION_PADDING, "Could not encrypt max size");
228 ck_assert_msg(c2len == -1, "incorrectly succeeded encrypting massive size");
229
230 m1plen = decrypt_data_fast(k, n, c1, c1len, m1prime);
231
232 ck_assert_msg(m1plen == sizeof(m1), "decrypted text lengths differ");
233 ck_assert_msg(memcmp(m1prime, m1, sizeof(m1)) == 0, "decrypted texts differ");
234}
235END_TEST
236
200#define DEFTESTCASE(NAME) \ 237#define DEFTESTCASE(NAME) \
201 TCase *NAME = tcase_create(#NAME); \ 238 TCase *NAME = tcase_create(#NAME); \
202 tcase_add_test(NAME, test_##NAME); \ 239 tcase_add_test(NAME, test_##NAME); \
@@ -209,6 +246,7 @@ Suite* crypto_suite(void)
209 DEFTESTCASE(known); 246 DEFTESTCASE(known);
210 DEFTESTCASE(fast_known); 247 DEFTESTCASE(fast_known);
211 DEFTESTCASE(endtoend); 248 DEFTESTCASE(endtoend);
249 DEFTESTCASE(large_data);
212 250
213 return s; 251 return s;
214} 252}
diff --git a/core/DHT.c b/core/DHT.c
index d359076d..1d13aa73 100644
--- a/core/DHT.c
+++ b/core/DHT.c
@@ -65,17 +65,6 @@
65 65
66typedef struct { 66typedef struct {
67 uint8_t client_id[CLIENT_ID_SIZE]; 67 uint8_t client_id[CLIENT_ID_SIZE];
68 IP_Port ip_port;
69 uint64_t timestamp;
70 uint64_t last_pinged;
71
72 /* Returned by this node. Either our friend or us */
73 IP_Port ret_ip_port;
74 uint64_t ret_timestamp;
75} Client_data;
76
77typedef struct {
78 uint8_t client_id[CLIENT_ID_SIZE];
79 Client_data client_list[MAX_FRIEND_CLIENTS]; 68 Client_data client_list[MAX_FRIEND_CLIENTS];
80 69
81 /* time at which the last get_nodes request was sent. */ 70 /* time at which the last get_nodes request was sent. */
@@ -115,6 +104,12 @@ static Pinged send_nodes[LSEND_NODES_ARRAY];
115 104
116/*----------------------------------------------------------------------------------*/ 105/*----------------------------------------------------------------------------------*/
117 106
107
108Client_data * DHT_get_close_list(void)
109{
110 return close_clientlist;
111}
112
118/* Compares client_id1 and client_id2 with client_id 113/* Compares client_id1 and client_id2 with client_id
119 * return 0 if both are same distance 114 * return 0 if both are same distance
120 * return 1 if client_id1 is closer 115 * return 1 if client_id1 is closer
@@ -633,6 +628,8 @@ static int handle_sendnodes(IP_Port source, uint8_t * packet, uint32_t length)
633 628
634int DHT_addfriend(uint8_t * client_id) 629int DHT_addfriend(uint8_t * client_id)
635{ 630{
631 if(friend_number(client_id) != -1) /*Is friend already in DHT?*/
632 return 1;
636 Friend * temp; 633 Friend * temp;
637 temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1)); 634 temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1));
638 if (temp == NULL) 635 if (temp == NULL)
@@ -930,49 +927,30 @@ static int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type)
930} 927}
931 928
932/* Handle a received ping request for */ 929/* Handle a received ping request for */
933static int handle_NATping(IP_Port source, uint8_t * packet, uint32_t length) 930static int handle_NATping(IP_Port source, uint8_t * source_pubkey, uint8_t * packet, uint32_t length)
934{ 931{
935 if (length < crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING 932 uint64_t ping_id;
936 || length > MAX_DATA_SIZE + ENCRYPTION_PADDING) 933 memcpy(&ping_id, packet + 1, sizeof(uint64_t));
937 return 1;
938
939 /* check if request is for us. */
940 if (id_equal(packet + 1, self_public_key)) {
941 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
942 uint8_t data[MAX_DATA_SIZE];
943
944 int len = handle_request(public_key, data, packet, length);
945 if (len != sizeof(uint64_t) + 1)
946 return 1;
947
948 uint64_t ping_id;
949 memcpy(&ping_id, data + 1, sizeof(uint64_t));
950 934
951 int friendnumber = friend_number(public_key); 935 int friendnumber = friend_number(source_pubkey);
952 if (friendnumber == -1) 936 if (friendnumber == -1)
953 return 1; 937 return 1;
954 938
955 Friend * friend = &friends_list[friendnumber]; 939 Friend * friend = &friends_list[friendnumber];
956 940
957 if (data[0] == 0) { 941 if (packet[0] == 0) {
958 /* 1 is reply */ 942 /* 1 is reply */
959 send_NATping(public_key, ping_id, 1); 943 send_NATping(source_pubkey, ping_id, 1);
960 friend->recvNATping_timestamp = unix_time(); 944 friend->recvNATping_timestamp = unix_time();
945 return 0;
946 } else if (packet[0] == 1) {
947 if (friend->NATping_id == ping_id) {
948 friend->NATping_id = ((uint64_t)random_int() << 32) + random_int();
949 friend->hole_punching = 1;
961 return 0; 950 return 0;
962 } else if (data[0] == 1) {
963 if (friend->NATping_id == ping_id) {
964 friend->NATping_id = ((uint64_t)random_int() << 32) + random_int();
965 friend->hole_punching = 1;
966 return 0;
967 }
968 } 951 }
969 return 1;
970 } 952 }
971 953 return 1;
972 /* if request is not for us, try routing it. */
973 route_packet(packet + 1, packet, length);
974
975 return 0;
976} 954}
977 955
978/* Get the most common ip in the ip_portlist 956/* Get the most common ip in the ip_portlist
@@ -1080,7 +1058,7 @@ void DHT_init(void)
1080 networking_registerhandler(1, &handle_ping_response); 1058 networking_registerhandler(1, &handle_ping_response);
1081 networking_registerhandler(2, &handle_getnodes); 1059 networking_registerhandler(2, &handle_getnodes);
1082 networking_registerhandler(3, &handle_sendnodes); 1060 networking_registerhandler(3, &handle_sendnodes);
1083 networking_registerhandler(254, &handle_NATping); 1061 cryptopacket_registerhandler(254, &handle_NATping);
1084} 1062}
1085 1063
1086void doDHT(void) 1064void doDHT(void)
diff --git a/core/DHT.h b/core/DHT.h
index 0e05f132..00a43d76 100644
--- a/core/DHT.h
+++ b/core/DHT.h
@@ -34,6 +34,19 @@ extern "C" {
34/* size of the client_id in bytes */ 34/* size of the client_id in bytes */
35#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES 35#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES
36 36
37typedef struct {
38 uint8_t client_id[CLIENT_ID_SIZE];
39 IP_Port ip_port;
40 uint64_t timestamp;
41 uint64_t last_pinged;
42
43 /* Returned by this node. Either our friend or us */
44 IP_Port ret_ip_port;
45 uint64_t ret_timestamp;
46} Client_data;
47
48Client_data * DHT_get_close_list(void);
49
37/* Add a new friend to the friends list 50/* Add a new friend to the friends list
38 client_id must be CLIENT_ID_SIZE bytes long. 51 client_id must be CLIENT_ID_SIZE bytes long.
39 returns 0 if success 52 returns 0 if success
diff --git a/core/Messenger.c b/core/Messenger.c
index 07145416..690a81b1 100644
--- a/core/Messenger.c
+++ b/core/Messenger.c
@@ -75,9 +75,9 @@ int getclient_id(Messenger *m, int friend_id, uint8_t *client_id)
75 75
76 return -1; 76 return -1;
77} 77}
78/* 78/*
79 * returns a uint16_t that represents the checksum of address of length len 79 * returns a uint16_t that represents the checksum of address of length len
80 * 80 *
81 * TODO: Another checksum algorithm might be better. 81 * TODO: Another checksum algorithm might be better.
82 */ 82 */
83static uint16_t address_checksum(uint8_t *address, uint32_t len) 83static uint16_t address_checksum(uint8_t *address, uint32_t len)
@@ -94,7 +94,7 @@ static uint16_t address_checksum(uint8_t *address, uint32_t len)
94/* 94/*
95 * returns a FRIEND_ADDRESS_SIZE byte address to give to others. 95 * returns a FRIEND_ADDRESS_SIZE byte address to give to others.
96 * format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)] 96 * format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
97 * 97 *
98 */ 98 */
99void getaddress(Messenger *m, uint8_t *address) 99void getaddress(Messenger *m, uint8_t *address)
100{ 100{
@@ -118,7 +118,7 @@ void getaddress(Messenger *m, uint8_t *address)
118 * return FAERR_ALREADYSENT if friend request already sent or already a friend 118 * return FAERR_ALREADYSENT if friend request already sent or already a friend
119 * return FAERR_UNKNOWN for unknown error 119 * return FAERR_UNKNOWN for unknown error
120 * return FAERR_BADCHECKSUM if bad checksum in address 120 * return FAERR_BADCHECKSUM if bad checksum in address
121 * return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different 121 * return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different
122 * (the nospam for that friend was set to the new one) 122 * (the nospam for that friend was set to the new one)
123 */ 123 */
124int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) 124int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length)
@@ -449,8 +449,7 @@ void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno)
449 m->friendlist[friendnumber].receives_read_receipts = yesno; 449 m->friendlist[friendnumber].receives_read_receipts = yesno;
450} 450}
451 451
452/* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); 452/* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); */
453static uint8_t friend_request_isset = 0; */
454/* set the function that will be executed when a friend request is received. */ 453/* set the function that will be executed when a friend request is received. */
455void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void*), void* userdata) 454void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void*), void* userdata)
456{ 455{
@@ -461,55 +460,48 @@ void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t
461void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata) 460void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
462{ 461{
463 m->friend_message = function; 462 m->friend_message = function;
464 m->friend_message_isset = 1;
465 m->friend_message_userdata = userdata; 463 m->friend_message_userdata = userdata;
466} 464}
467 465
468void m_callback_action(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata) 466void m_callback_action(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
469{ 467{
470 m->friend_action = function; 468 m->friend_action = function;
471 m->friend_action_isset = 1;
472 m->friend_action_userdata = userdata; 469 m->friend_action_userdata = userdata;
473} 470}
474 471
475void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata) 472void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
476{ 473{
477 m->friend_namechange = function; 474 m->friend_namechange = function;
478 m->friend_namechange_isset = 1;
479 m->friend_namechange_userdata = userdata; 475 m->friend_namechange_userdata = userdata;
480} 476}
481 477
482void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata) 478void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
483{ 479{
484 m->friend_statusmessagechange = function; 480 m->friend_statusmessagechange = function;
485 m->friend_statusmessagechange_isset = 1;
486 m->friend_statuschange_userdata = userdata; 481 m->friend_statuschange_userdata = userdata;
487} 482}
488 483
489void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void*), void* userdata) 484void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void*), void* userdata)
490{ 485{
491 m->friend_userstatuschange = function; 486 m->friend_userstatuschange = function;
492 m->friend_userstatuschange_isset = 1;
493 m->friend_userstatuschange_userdata = userdata; 487 m->friend_userstatuschange_userdata = userdata;
494} 488}
495 489
496void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void*), void* userdata) 490void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void*), void* userdata)
497{ 491{
498 m->read_receipt = function; 492 m->read_receipt = function;
499 m->read_receipt_isset = 1;
500 m->read_receipt_userdata = userdata; 493 m->read_receipt_userdata = userdata;
501} 494}
502 495
503void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void*), void* userdata) 496void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void*), void* userdata)
504{ 497{
505 m->friend_connectionstatuschange = function; 498 m->friend_connectionstatuschange = function;
506 m->friend_connectionstatuschange_isset = 1;
507 m->friend_connectionstatuschange_userdata = userdata; 499 m->friend_connectionstatuschange_userdata = userdata;
508} 500}
509 501
510static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_t status) 502static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_t status)
511{ 503{
512 if (!m->friend_connectionstatuschange_isset) 504 if (!m->friend_connectionstatuschange)
513 return; 505 return;
514 if (status == NOFRIEND) 506 if (status == NOFRIEND)
515 return; 507 return;
@@ -580,7 +572,10 @@ Messenger * initMessenger(void)
580 572
581/* run this before closing shop */ 573/* run this before closing shop */
582void cleanupMessenger(Messenger *m){ 574void cleanupMessenger(Messenger *m){
583 /* FIXME TODO it seems no one frees friendlist or all the elements status */ 575 /* FIXME TODO ideally cleanupMessenger will mirror initMessenger
576 * this requires the other modules to expose cleanup functions
577 */
578 free(m->friendlist);
584 free(m); 579 free(m);
585} 580}
586 581
@@ -648,7 +643,7 @@ void doFriends(Messenger *m)
648 case PACKET_ID_NICKNAME: { 643 case PACKET_ID_NICKNAME: {
649 if (data_length >= MAX_NAME_LENGTH || data_length == 0) 644 if (data_length >= MAX_NAME_LENGTH || data_length == 0)
650 break; 645 break;
651 if(m->friend_namechange_isset) 646 if(m->friend_namechange)
652 m->friend_namechange(m, i, data, data_length, m->friend_namechange_userdata); 647 m->friend_namechange(m, i, data, data_length, m->friend_namechange_userdata);
653 memcpy(m->friendlist[i].name, data, data_length); 648 memcpy(m->friendlist[i].name, data, data_length);
654 m->friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */ 649 m->friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */
@@ -659,7 +654,7 @@ void doFriends(Messenger *m)
659 break; 654 break;
660 uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1); 655 uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1);
661 memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); 656 memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
662 if (m->friend_statusmessagechange_isset) 657 if (m->friend_statusmessagechange)
663 m->friend_statusmessagechange(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 658 m->friend_statusmessagechange(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH),
664 m->friend_statuschange_userdata); 659 m->friend_statuschange_userdata);
665 set_friend_statusmessage(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH)); 660 set_friend_statusmessage(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
@@ -670,7 +665,7 @@ void doFriends(Messenger *m)
670 if (data_length != 1) 665 if (data_length != 1)
671 break; 666 break;
672 USERSTATUS status = data[0]; 667 USERSTATUS status = data[0];
673 if (m->friend_userstatuschange_isset) 668 if (m->friend_userstatuschange)
674 m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata); 669 m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata);
675 set_friend_userstatus(m, i, status); 670 set_friend_userstatus(m, i, status);
676 break; 671 break;
@@ -683,12 +678,12 @@ void doFriends(Messenger *m)
683 if (m->friendlist[i].receives_read_receipts) { 678 if (m->friendlist[i].receives_read_receipts) {
684 write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); 679 write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length);
685 } 680 }
686 if (m->friend_message_isset) 681 if (m->friend_message)
687 (*m->friend_message)(m, i, message, message_length, m->friend_message_userdata); 682 (*m->friend_message)(m, i, message, message_length, m->friend_message_userdata);
688 break; 683 break;
689 } 684 }
690 case PACKET_ID_ACTION: { 685 case PACKET_ID_ACTION: {
691 if (m->friend_action_isset) 686 if (m->friend_action)
692 (*m->friend_action)(m, i, data, data_length, m->friend_action_userdata); 687 (*m->friend_action)(m, i, data, data_length, m->friend_action_userdata);
693 break; 688 break;
694 } 689 }
@@ -698,7 +693,7 @@ void doFriends(Messenger *m)
698 break; 693 break;
699 memcpy(&msgid, data, sizeof(msgid)); 694 memcpy(&msgid, data, sizeof(msgid));
700 msgid = ntohl(msgid); 695 msgid = ntohl(msgid);
701 if (m->read_receipt_isset) 696 if (m->read_receipt)
702 (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata); 697 (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata);
703 break; 698 break;
704 } 699 }
@@ -744,7 +739,7 @@ void doMessenger(Messenger *m)
744 doNetCrypto(); 739 doNetCrypto();
745 doInbound(m); 740 doInbound(m);
746 doFriends(m); 741 doFriends(m);
747 742
748 timer_poll(); 743 timer_poll();
749} 744}
750 745
diff --git a/core/Messenger.h b/core/Messenger.h
index 9621176f..a2add19d 100644
--- a/core/Messenger.h
+++ b/core/Messenger.h
@@ -111,28 +111,20 @@ typedef struct Messenger {
111 uint32_t numfriends; 111 uint32_t numfriends;
112 112
113 void (*friend_message)(struct Messenger *m, int, uint8_t *, uint16_t, void*); 113 void (*friend_message)(struct Messenger *m, int, uint8_t *, uint16_t, void*);
114 uint8_t friend_message_isset;
115 void* friend_message_userdata; 114 void* friend_message_userdata;
116 void (*friend_action)(struct Messenger *m, int, uint8_t *, uint16_t, void*); 115 void (*friend_action)(struct Messenger *m, int, uint8_t *, uint16_t, void*);
117 uint8_t friend_action_isset;
118 void* friend_action_userdata; 116 void* friend_action_userdata;
119 void (*friend_namechange)(struct Messenger *m, int, uint8_t *, uint16_t, void*); 117 void (*friend_namechange)(struct Messenger *m, int, uint8_t *, uint16_t, void*);
120 uint8_t friend_namechange_isset;
121 void* friend_namechange_userdata; 118 void* friend_namechange_userdata;
122 void (*friend_statusmessagechange)(struct Messenger *m, int, uint8_t *, uint16_t, void*); 119 void (*friend_statusmessagechange)(struct Messenger *m, int, uint8_t *, uint16_t, void*);
123 uint8_t friend_statusmessagechange_isset;
124 void* friend_statusmessagechange_userdata; 120 void* friend_statusmessagechange_userdata;
125 void (*friend_userstatuschange)(struct Messenger *m, int, USERSTATUS, void*); 121 void (*friend_userstatuschange)(struct Messenger *m, int, USERSTATUS, void*);
126 uint8_t friend_userstatuschange_isset;
127 void* friend_userstatuschange_userdata; 122 void* friend_userstatuschange_userdata;
128 void (*read_receipt)(struct Messenger *m, int, uint32_t, void*); 123 void (*read_receipt)(struct Messenger *m, int, uint32_t, void*);
129 uint8_t read_receipt_isset;
130 void* read_receipt_userdata; 124 void* read_receipt_userdata;
131 void (*friend_statuschange)(struct Messenger *m, int, uint8_t, void*); 125 void (*friend_statuschange)(struct Messenger *m, int, uint8_t, void*);
132 uint8_t friend_statuschange_isset;
133 void* friend_statuschange_userdata; 126 void* friend_statuschange_userdata;
134 void (*friend_connectionstatuschange)(struct Messenger *m, int, uint8_t, void*); 127 void (*friend_connectionstatuschange)(struct Messenger *m, int, uint8_t, void*);
135 uint8_t friend_connectionstatuschange_isset;
136 void* friend_connectionstatuschange_userdata; 128 void* friend_connectionstatuschange_userdata;
137 129
138 130
@@ -141,7 +133,7 @@ typedef struct Messenger {
141/* 133/*
142 * returns a FRIEND_ADDRESS_SIZE byte address to give to others. 134 * returns a FRIEND_ADDRESS_SIZE byte address to give to others.
143 * format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)] 135 * format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
144 * 136 *
145 */ 137 */
146void getaddress(Messenger *m, uint8_t *address); 138void getaddress(Messenger *m, uint8_t *address);
147 139
@@ -157,7 +149,7 @@ void getaddress(Messenger *m, uint8_t *address);
157 * return -4 if friend request already sent or already a friend 149 * return -4 if friend request already sent or already a friend
158 * return -5 for unknown error 150 * return -5 for unknown error
159 * return -6 if bad checksum in address 151 * return -6 if bad checksum in address
160 * return -7 if the friend was already there but the nospam was different 152 * return -7 if the friend was already there but the nospam was different
161 * (the nospam for that friend was set to the new one) 153 * (the nospam for that friend was set to the new one)
162 */ 154 */
163int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length); 155int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length);
diff --git a/core/friend_requests.c b/core/friend_requests.c
index 8276db29..ae19ebdd 100644
--- a/core/friend_requests.c
+++ b/core/friend_requests.c
@@ -123,39 +123,23 @@ static int request_received(uint8_t * client_id)
123} 123}
124 124
125 125
126static int friendreq_handlepacket(IP_Port source, uint8_t * packet, uint32_t length) 126static int friendreq_handlepacket(IP_Port source, uint8_t * source_pubkey, uint8_t * packet, uint32_t length)
127{ 127{
128 if (packet[0] == 32) { 128 if (handle_friendrequest_isset == 0)
129 if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING || 129 return 1;
130 length > MAX_DATA_SIZE + ENCRYPTION_PADDING) 130 if (length <= sizeof(nospam))
131 return 1; 131 return 1;
132 if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us. 132 if (request_received(source_pubkey))
133 if (handle_friendrequest_isset == 0) 133 return 1;
134 return 1; 134 if (memcmp(packet, &nospam, sizeof(nospam)) != 0)
135 135 return 1;
136 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 136
137 uint8_t data[MAX_DATA_SIZE]; 137 addto_receivedlist(source_pubkey);
138 int len = handle_request(public_key, data, packet, length); 138 (*handle_friendrequest)(source_pubkey, packet + 4, length - 4, handle_friendrequest_userdata);
139 if (len == -1) 139 return 0;
140 return 1;
141 if (len <= sizeof(nospam))
142 return 1;
143 if (request_received(public_key))
144 return 1;
145 if (memcmp(data, &nospam, sizeof(nospam)) != 0)
146 return 1;
147
148 addto_receivedlist(public_key);
149 (*handle_friendrequest)(public_key, data + 4, len - 4, handle_friendrequest_userdata);
150 } else { /* if request is not for us, try routing it. */
151 if(route_packet(packet + 1, packet, length) == length)
152 return 0;
153 }
154 }
155 return 1;
156} 140}
157 141
158void friendreq_init(void) 142void friendreq_init(void)
159{ 143{
160 networking_registerhandler(32, &friendreq_handlepacket); 144 cryptopacket_registerhandler(32, &friendreq_handlepacket);
161} 145}
diff --git a/core/net_crypto.c b/core/net_crypto.c
index 07c43c40..376708ab 100644
--- a/core/net_crypto.c
+++ b/core/net_crypto.c
@@ -71,33 +71,6 @@ uint8_t crypto_iszero(uint8_t *mem, uint32_t length)
71 return check; // We return zero if mem is made out of zeroes. 71 return check; // We return zero if mem is made out of zeroes.
72} 72}
73 73
74/* encrypts plain of length length to encrypted of length + 16 using the
75 public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce
76 return -1 if there was a problem.
77 return length of encrypted data if everything was fine. */
78int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
79 uint8_t *plain, uint32_t length, uint8_t *encrypted)
80{
81 if (length + crypto_box_MACBYTES > MAX_DATA_SIZE || length == 0)
82 return -1;
83
84 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0};
85 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES];
86
87 memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */
88
89 crypto_box(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, public_key, secret_key);
90
91 /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero
92 apparently memcmp should not be used so we do this instead:*/
93 if(crypto_iszero(temp_encrypted, crypto_box_BOXZEROBYTES) != 0)
94 return -1;
95
96 /* unpad the encrypted message */
97 memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES);
98 return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES;
99}
100
101/* Precomputes the shared key from their public_key and our secret_key. 74/* Precomputes the shared key from their public_key and our secret_key.
102 This way we can avoid an expensive elliptic curve scalar multiply for each 75 This way we can avoid an expensive elliptic curve scalar multiply for each
103 encrypt/decrypt operation. 76 encrypt/decrypt operation.
@@ -114,7 +87,7 @@ int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce,
114 if (length + crypto_box_MACBYTES > MAX_DATA_SIZE || length == 0) 87 if (length + crypto_box_MACBYTES > MAX_DATA_SIZE || length == 0)
115 return -1; 88 return -1;
116 89
117 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0}; 90 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0};
118 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES]; 91 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES];
119 92
120 memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */ 93 memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */
@@ -129,35 +102,6 @@ int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce,
129 return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES; 102 return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES;
130} 103}
131 104
132/* decrypts encrypted of length length to plain of length length - 16 using the
133 public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce
134 return -1 if there was a problem(decryption failed)
135 return length of plain data if everything was fine. */
136int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
137 uint8_t *encrypted, uint32_t length, uint8_t *plain)
138{
139 if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES)
140 return -1;
141
142 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES];
143 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0};
144
145 memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */
146
147 if (crypto_box_open(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES,
148 nonce, public_key, secret_key) == -1)
149 return -1;
150
151 /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero
152 apparently memcmp should not be used so we do this instead:*/
153 if(crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0)
154 return -1;
155
156 /* unpad the plain message */
157 memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES);
158 return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES;
159}
160
161/* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ 105/* Fast decrypt. Depends on enc_ley from encrypt_precompute. */
162int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, 106int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce,
163 uint8_t *encrypted, uint32_t length, uint8_t *plain) 107 uint8_t *encrypted, uint32_t length, uint8_t *plain)
@@ -165,7 +109,7 @@ int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce,
165 if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) 109 if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES)
166 return -1; 110 return -1;
167 111
168 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES]; 112 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES];
169 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0}; 113 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0};
170 114
171 memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */ 115 memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */
@@ -184,6 +128,22 @@ int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce,
184 return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; 128 return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES;
185} 129}
186 130
131int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
132 uint8_t *plain, uint32_t length, uint8_t *encrypted)
133{
134 uint8_t k[crypto_box_BEFORENMBYTES];
135 encrypt_precompute(public_key, secret_key, k);
136 return encrypt_data_fast(k, nonce, plain, length, encrypted);
137}
138
139int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
140 uint8_t *encrypted, uint32_t length, uint8_t *plain)
141{
142 uint8_t k[crypto_box_BEFORENMBYTES];
143 encrypt_precompute(public_key, secret_key, k);
144 return decrypt_data_fast(k, nonce, encrypted, length, plain);
145}
146
187/* increment the given nonce by 1 */ 147/* increment the given nonce by 1 */
188static void increment_nonce(uint8_t *nonce) 148static void increment_nonce(uint8_t *nonce)
189{ 149{
@@ -261,15 +221,18 @@ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length)
261 returns the length of the created packet on success */ 221 returns the length of the created packet on success */
262int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t length, uint8_t request_id) 222int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t length, uint8_t request_id)
263{ 223{
264 if (MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING) 224 if (MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING)
265 return -1; 225 return -1;
266 uint8_t nonce[crypto_box_NONCEBYTES]; 226 uint8_t nonce[crypto_box_NONCEBYTES];
227 uint8_t temp[MAX_DATA_SIZE];
228 memcpy(temp + 1, data, length);
229 temp[0] = request_id;
267 random_nonce(nonce); 230 random_nonce(nonce);
268 int len = encrypt_data(public_key, self_secret_key, nonce, data, length, 231 int len = encrypt_data(public_key, self_secret_key, nonce, temp, length,
269 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); 232 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet);
270 if (len == -1) 233 if (len == -1)
271 return -1; 234 return -1;
272 packet[0] = request_id; 235 packet[0] = 32;
273 memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); 236 memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
274 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, self_public_key, crypto_box_PUBLICKEYBYTES); 237 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, self_public_key, crypto_box_PUBLICKEYBYTES);
275 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); 238 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES);
@@ -281,7 +244,7 @@ int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t
281 in data if a friend or ping request was sent to us and returns the length of the data. 244 in data if a friend or ping request was sent to us and returns the length of the data.
282 packet is the request packet and length is its length 245 packet is the request packet and length is its length
283 return -1 if not valid request. */ 246 return -1 if not valid request. */
284int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *packet, uint16_t length) 247static int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *request_id, uint8_t *packet, uint16_t length)
285{ 248{
286 249
287 if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && 250 if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING &&
@@ -289,16 +252,51 @@ int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *packet, uint16_t
289 memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { 252 memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {
290 memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); 253 memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES);
291 uint8_t nonce[crypto_box_NONCEBYTES]; 254 uint8_t nonce[crypto_box_NONCEBYTES];
255 uint8_t temp[MAX_DATA_SIZE];
292 memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); 256 memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES);
293 int len1 = decrypt_data(public_key, self_secret_key, nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, 257 int len1 = decrypt_data(public_key, self_secret_key, nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES,
294 length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), data); 258 length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp);
295 if(len1 == -1) 259 if(len1 == -1 || len1 == 0)
296 return -1; 260 return -1;
261 request_id[0] = temp[0];
262 --len1;
263 memcpy(data, temp + 1, len1);
297 return len1; 264 return len1;
298 } else 265 } else
299 return -1; 266 return -1;
300} 267}
301 268
269static cryptopacket_handler_callback cryptopackethandlers[256] = {0};
270
271void cryptopacket_registerhandler(uint8_t byte, cryptopacket_handler_callback cb)
272{
273 cryptopackethandlers[byte] = cb;
274}
275
276static int cryptopacket_handle(IP_Port source, uint8_t * packet, uint32_t length)
277{
278 if (packet[0] == 32) {
279 if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING ||
280 length > MAX_DATA_SIZE + ENCRYPTION_PADDING)
281 return 1;
282 if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us.
283 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
284 uint8_t data[MAX_DATA_SIZE];
285 uint8_t number;
286 int len = handle_request(public_key, data, &number, packet, length);
287 if (len == -1 || len == 0)
288 return 1;
289 if (!cryptopackethandlers[number]) return 1;
290 cryptopackethandlers[number](source, public_key, data, len - 1);
291
292 } else { /* if request is not for us, try routing it. */
293 if(route_packet(packet + 1, packet, length) == length)
294 return 0;
295 }
296 }
297 return 1;
298}
299
302/* Send a crypto handshake packet containing an encrypted secret nonce and session public key 300/* Send a crypto handshake packet containing an encrypted secret nonce and session public key
303 to peer with connection_id and public_key 301 to peer with connection_id and public_key
304 the packet is encrypted with a random nonce which is sent in plain text with the packet */ 302 the packet is encrypted with a random nonce which is sent in plain text with the packet */
@@ -619,6 +617,7 @@ void initNetCrypto(void)
619{ 617{
620 memset(crypto_connections, 0 ,sizeof(crypto_connections)); 618 memset(crypto_connections, 0 ,sizeof(crypto_connections));
621 memset(incoming_connections, -1 ,sizeof(incoming_connections)); 619 memset(incoming_connections, -1 ,sizeof(incoming_connections));
620 networking_registerhandler(32, &cryptopacket_handle);
622 uint32_t i; 621 uint32_t i;
623 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) 622 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i)
624 crypto_connections[i].number = ~0; 623 crypto_connections[i].number = ~0;
diff --git a/core/net_crypto.h b/core/net_crypto.h
index 135e099d..570b9373 100644
--- a/core/net_crypto.h
+++ b/core/net_crypto.h
@@ -25,6 +25,7 @@
25#define NET_CRYPTO_H 25#define NET_CRYPTO_H
26 26
27#include "Lossless_UDP.h" 27#include "Lossless_UDP.h"
28#include "DHT.h"
28 29
29#ifdef __cplusplus 30#ifdef __cplusplus
30extern "C" { 31extern "C" {
@@ -88,11 +89,10 @@ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length);
88 returns the length of the created packet on success */ 89 returns the length of the created packet on success */
89int create_request(uint8_t *packet, uint8_t * public_key, uint8_t *data, uint32_t length, uint8_t request_id); 90int create_request(uint8_t *packet, uint8_t * public_key, uint8_t *data, uint32_t length, uint8_t request_id);
90 91
91/* puts the senders public key in the request in public_key, the data from the request 92
92 in data if a friend or ping request was sent to us and returns the length of the data. 93typedef int (*cryptopacket_handler_callback)(IP_Port ip_port, uint8_t * source_pubkey, uint8_t *data, uint32_t len);
93 packet is the request packet and length is its length 94/* Function to call when request beginning with byte is received */
94 return -1 if not valid request. */ 95void cryptopacket_registerhandler(uint8_t byte, cryptopacket_handler_callback cb);
95int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *packet, uint16_t length);
96 96
97/* Start a secure connection with other peer who has public_key and ip_port 97/* Start a secure connection with other peer who has public_key and ip_port
98 returns -1 if failure 98 returns -1 if failure
diff --git a/other/tox.png b/other/tox.png
new file mode 100644
index 00000000..e3d68696
--- /dev/null
+++ b/other/tox.png
Binary files differ
diff --git a/testing/DHT_test.c b/testing/DHT_test.c
index 350093fd..c5b367cf 100644
--- a/testing/DHT_test.c
+++ b/testing/DHT_test.c
@@ -53,10 +53,10 @@ void print_clientlist()
53 uint32_t i, j; 53 uint32_t i, j;
54 IP_Port p_ip; 54 IP_Port p_ip;
55 printf("___________________CLOSE________________________________\n"); 55 printf("___________________CLOSE________________________________\n");
56 for(i = 0; i < 4; i++) { 56 for(i = 0; i < 32; i++) {
57 printf("ClientID: "); 57 printf("ClientID: ");
58 for(j = 0; j < 32; j++) { 58 for(j = 0; j < 32; j++) {
59 printf("%hhX", close_clientlist[i].client_id[j]); 59 printf("%02hhX", close_clientlist[i].client_id[j]);
60 } 60 }
61 p_ip = close_clientlist[i].ip_port; 61 p_ip = close_clientlist[i].ip_port;
62 printf("\nIP: %u.%u.%u.%u Port: %u",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port)); 62 printf("\nIP: %u.%u.%u.%u Port: %u",p_ip.ip.c[0],p_ip.ip.c[1],p_ip.ip.c[2],p_ip.ip.c[3],ntohs(p_ip.port));
diff --git a/testing/nTox.c b/testing/nTox.c
index cab2d158..ead4fd21 100644
--- a/testing/nTox.c
+++ b/testing/nTox.c
@@ -52,28 +52,15 @@ uint8_t num_requests = 0;
52 52
53void get_id(Messenger *m, char *data) 53void get_id(Messenger *m, char *data)
54{ 54{
55 char idstring0[200]; 55 sprintf(data, "[i] ID: ");
56 char idstring1[FRIEND_ADDRESS_SIZE][5]; 56 int offset = strlen(data);
57 char idstring2[FRIEND_ADDRESS_SIZE][5];
58 int i = 0; 57 int i = 0;
59 uint8_t address[FRIEND_ADDRESS_SIZE]; 58 uint8_t address[FRIEND_ADDRESS_SIZE];
60 getaddress(m, address); 59 getaddress(m, address);
61 for(i = 0; i < FRIEND_ADDRESS_SIZE; i++) 60 for(; i < FRIEND_ADDRESS_SIZE; i++)
62 { 61 {
63 if (address[i] < (FRIEND_ADDRESS_SIZE / 2)) 62 sprintf(data + 2*i + offset, "%02X ", address[i]);
64 strcpy(idstring1[i],"0");
65 else
66 strcpy(idstring1[i], "");
67 sprintf(idstring2[i], "%hhX",address[i]);
68 } 63 }
69 strcpy(idstring0,"[i] ID: ");
70 int j = 0;
71 for (j = 0; j < FRIEND_ADDRESS_SIZE; j++) {
72 strcat(idstring0,idstring1[j]);
73 strcat(idstring0,idstring2[j]);
74 }
75
76 memcpy(data, idstring0, strlen(idstring0));
77} 64}
78 65
79void new_lines(char *line) 66void new_lines(char *line)
diff --git a/testing/toxic/CMakeLists.txt b/testing/toxic/CMakeLists.txt
index 13b8692d..9ee7020e 100644
--- a/testing/toxic/CMakeLists.txt
+++ b/testing/toxic/CMakeLists.txt
@@ -8,8 +8,10 @@ set(exe_name toxic)
8 8
9add_executable(${exe_name} 9add_executable(${exe_name}
10 main.c 10 main.c
11 windows.c
11 prompt.c 12 prompt.c
12 friendlist.c 13 friendlist.c
14 dhtstatus.c
13 chat.c 15 chat.c
14 configdir.c) 16 configdir.c)
15 17
diff --git a/testing/toxic/chat.c b/testing/toxic/chat.c
index 1b5e743d..d5edf956 100644
--- a/testing/toxic/chat.c
+++ b/testing/toxic/chat.c
@@ -13,6 +13,8 @@
13#include "../../core/network.h" 13#include "../../core/network.h"
14 14
15#include "windows.h" 15#include "windows.h"
16#include "friendlist.h"
17#include "chat.h"
16 18
17#define CURS_Y_OFFSET 3 19#define CURS_Y_OFFSET 3
18 20
@@ -24,10 +26,6 @@ typedef struct {
24 WINDOW* linewin; 26 WINDOW* linewin;
25} ChatContext; 27} ChatContext;
26 28
27extern int active_window;
28
29extern void del_window(ToxWindow *w, int f_num);
30extern void fix_name(uint8_t *name);
31void print_help(ChatContext *self); 29void print_help(ChatContext *self);
32void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd); 30void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd);
33 31
@@ -316,11 +314,10 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd)
316 snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); 314 snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff);
317 strcat(id, xx); 315 strcat(id, xx);
318 } 316 }
319 wprintw(ctx->history, "Your ID: %s\n", id); 317 wprintw(ctx->history, "%s\n", id);
320 } 318 }
321 319
322 else if (strcmp(ctx->line, "/close") == 0) { 320 else if (strcmp(ctx->line, "/close") == 0) {
323 active_window = 0; // Go to prompt screen
324 int f_num = ctx->friendnum; 321 int f_num = ctx->friendnum;
325 delwin(ctx->linewin); 322 delwin(ctx->linewin);
326 del_window(self, f_num); 323 del_window(self, f_num);
diff --git a/testing/toxic/chat.h b/testing/toxic/chat.h
new file mode 100644
index 00000000..7599d462
--- /dev/null
+++ b/testing/toxic/chat.h
@@ -0,0 +1,6 @@
1#ifndef CHAT_H_6489PZ13
2#define CHAT_H_6489PZ13
3
4ToxWindow new_chat(Messenger *m, int friendnum);
5
6#endif /* end of include guard: CHAT_H_6489PZ13 */
diff --git a/testing/toxic/dhtstatus.c b/testing/toxic/dhtstatus.c
new file mode 100644
index 00000000..66268900
--- /dev/null
+++ b/testing/toxic/dhtstatus.c
@@ -0,0 +1,89 @@
1#include "dhtstatus.h"
2#include "string.h"
3#include "../../core/network.h"
4#include "../../core/DHT.h"
5
6typedef uint8_t ipbuf[3*4+3+1];
7static int num_selected = 0;
8
9static void printip(ipbuf buf, IP ip)
10{
11 sprintf((char*)buf, "%u.%u.%u.%u", ip.c[0], ip.c[1], ip.c[2], ip.c[3]);
12}
13
14static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key)
15{
16 switch(key) {
17 case KEY_UP:
18 case 'k':
19 if (--num_selected < 0)
20 num_selected = CLIENT_ID_SIZE-1;
21 break;
22
23 case KEY_DOWN:
24 case 'j':
25 num_selected = (num_selected+1) % CLIENT_ID_SIZE;
26 break;
27
28 case '\n':
29 break;
30
31 default:
32 break;
33 }
34}
35
36static void dhtstatus_onDraw(ToxWindow *self)
37{
38 Client_data * close_clientlist = DHT_get_close_list();
39 curs_set(0);
40 werase(self->window);
41
42 uint64_t now = unix_time();
43 uint32_t i, j;
44 ipbuf ipbuf;
45 wprintw(self->window,"\n%llu ______________________ CLOSE LIST ________________________ ___ IP ADDR ___ _PRT_ LST PNG ____ SELF ____ _PRT_ LST\n\n", now);
46 for(i = 0; i < CLIENT_ID_SIZE; i++) {
47 Client_data * client = close_clientlist + i;
48 if (i == num_selected) wattron(self->window, COLOR_PAIR(3));
49 wprintw(self->window,"[%02i] ", i);
50 uint16_t port = ntohs(client->ip_port.port);
51 if(port) {
52 for(j = 0; j < 32; j++)
53 wprintw(self->window, "%02hhx", client->client_id[j]);
54
55 printip(ipbuf, client->ip_port.ip);
56 wprintw(self->window, " %15s %5u ", ipbuf, port);
57 wprintw(self->window, " %3llu ", now - client->timestamp);
58 wprintw(self->window, " %3llu ", now - client->last_pinged);
59
60 port = ntohs(client->ret_ip_port.port);
61 if(port) {
62 printip(ipbuf, client->ret_ip_port.ip);
63 wprintw(self->window, " %15s %5u %3llu", ipbuf, port, now - close_clientlist[i].ret_timestamp);
64 }
65 }
66 wprintw(self->window, "\n");
67 if (i == num_selected) wattroff(self->window, COLOR_PAIR(3));
68 }
69
70 wrefresh(self->window);
71}
72
73static void dhtstatus_onInit(ToxWindow *self, Messenger *m)
74{
75
76}
77
78ToxWindow new_dhtstatus()
79{
80 ToxWindow ret;
81 memset(&ret, 0, sizeof(ret));
82
83 ret.onKey = &dhtstatus_onKey;
84 ret.onDraw = &dhtstatus_onDraw;
85 ret.onInit = &dhtstatus_onInit;
86
87 strcpy(ret.title, "[dht status]");
88 return ret;
89}
diff --git a/testing/toxic/dhtstatus.h b/testing/toxic/dhtstatus.h
new file mode 100644
index 00000000..2b30e5a3
--- /dev/null
+++ b/testing/toxic/dhtstatus.h
@@ -0,0 +1,8 @@
1#ifndef _dhtstatus_h
2#define _dhtstatus_h
3
4#include "windows.h"
5
6ToxWindow new_dhtstatus();
7
8#endif
diff --git a/testing/toxic/friendlist.c b/testing/toxic/friendlist.c
index 56061cf9..e7504fbf 100644
--- a/testing/toxic/friendlist.c
+++ b/testing/toxic/friendlist.c
@@ -11,12 +11,9 @@
11#include "../../core/network.h" 11#include "../../core/network.h"
12 12
13#include "windows.h" 13#include "windows.h"
14#include "friendlist.h"
14 15
15extern char WINDOW_STATUS[TOXWINDOWS_MAX_NUM]; 16static char * WINDOW_STATUS;
16extern int add_window(ToxWindow w, int n);
17extern ToxWindow new_chat(Messenger *m, int friendnum);
18
19extern int active_window;
20 17
21typedef struct { 18typedef struct {
22 uint8_t name[MAX_NAME_LENGTH]; 19 uint8_t name[MAX_NAME_LENGTH];
@@ -54,8 +51,7 @@ void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str,
54 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { 51 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
55 if (WINDOW_STATUS[i] == -1) { 52 if (WINDOW_STATUS[i] == -1) {
56 WINDOW_STATUS[i] = num; 53 WINDOW_STATUS[i] = num;
57 add_window(new_chat(m, num), i); 54 add_window(m, new_chat(m, num), i);
58 active_window = i;
59 break; 55 break;
60 } 56 }
61 } 57 }
@@ -111,7 +107,7 @@ static void friendlist_onKey(ToxWindow *self, Messenger *m, int key)
111 int i; 107 int i;
112 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { 108 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
113 if (WINDOW_STATUS[i] == num_selected) { 109 if (WINDOW_STATUS[i] == num_selected) {
114 active_window = i; 110 set_active_window(i);
115 break; 111 break;
116 } 112 }
117 } 113 }
@@ -121,8 +117,7 @@ static void friendlist_onKey(ToxWindow *self, Messenger *m, int key)
121 if (WINDOW_STATUS[i] == -1) { 117 if (WINDOW_STATUS[i] == -1) {
122 WINDOW_STATUS[i] = num_selected; 118 WINDOW_STATUS[i] = num_selected;
123 friends[num_selected].chatwin = num_selected; 119 friends[num_selected].chatwin = num_selected;
124 add_window(new_chat(m, num_selected), i); 120 add_window(m, new_chat(m, num_selected), i);
125 active_window = i;
126 break; 121 break;
127 } 122 }
128 } 123 }
@@ -169,7 +164,8 @@ static void friendlist_onInit(ToxWindow *self, Messenger *m)
169 164
170} 165}
171 166
172ToxWindow new_friendlist() { 167ToxWindow new_friendlist(char * ws) {
168 WINDOW_STATUS = ws;
173 ToxWindow ret; 169 ToxWindow ret;
174 memset(&ret, 0, sizeof(ret)); 170 memset(&ret, 0, sizeof(ret));
175 171
diff --git a/testing/toxic/friendlist.h b/testing/toxic/friendlist.h
new file mode 100644
index 00000000..c3d8dac7
--- /dev/null
+++ b/testing/toxic/friendlist.h
@@ -0,0 +1,12 @@
1#ifndef FRIENDLIST_H_53I41IM
2#define FRIENDLIST_H_53I41IM
3
4#include "windows.h"
5#include "chat.h"
6
7ToxWindow new_friendlist(char * ws);
8int friendlist_onFriendAdded(Messenger *m, int num);
9void disable_chatwin(int f_num);
10void fix_name(uint8_t *name);
11
12#endif /* end of include guard: FRIENDLIST_H_53I41IM */
diff --git a/testing/toxic/main.c b/testing/toxic/main.c
index e9d285cc..aa025a1a 100644
--- a/testing/toxic/main.c
+++ b/testing/toxic/main.c
@@ -8,6 +8,7 @@
8#include <stdlib.h> 8#include <stdlib.h>
9#include <stdbool.h> 9#include <stdbool.h>
10#include <stdint.h> 10#include <stdint.h>
11#include <signal.h>
11 12
12#ifdef _win32 13#ifdef _win32
13#include <direct.h> 14#include <direct.h>
@@ -21,104 +22,21 @@
21 22
22#include "configdir.h" 23#include "configdir.h"
23#include "windows.h" 24#include "windows.h"
25#include "prompt.h"
26#include "friendlist.h"
24 27
25extern ToxWindow new_prompt();
26extern ToxWindow new_friendlist();
27 28
28extern int friendlist_onFriendAdded(Messenger *m, int num); 29void on_window_resize(int sig)
29extern void disable_chatwin(int f_num);
30extern int add_req(uint8_t *public_key); // XXX
31extern unsigned char *hex_string_to_bin(char hex_string[]);
32
33static int store_data(char*);
34
35/* Holds status of chat windows */
36char WINDOW_STATUS[MAX_WINDOW_SLOTS];
37
38#ifndef TOXICVER
39#define TOXICVER "NOVER" //Use the -D flag to set this
40#endif
41
42static ToxWindow windows[MAX_WINDOW_SLOTS];
43static ToxWindow* prompt;
44
45static Messenger *m;
46static char *DATA_FILE;
47
48int w_num;
49int active_window;
50
51/* CALLBACKS START */
52void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void* userdata)
53{
54 int n = add_req(public_key);
55 wprintw(prompt->window, "\nFriend request from:\n");
56
57 int i;
58 for (i = 0; i < KEY_SIZE_BYTES; ++i) {
59 wprintw(prompt->window, "%02x", public_key[i] & 0xff);
60 }
61
62 wprintw(prompt->window, "\nWith the message: %s\n", data);
63 wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n);
64
65 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
66 if (windows[i].onFriendRequest != NULL)
67 windows[i].onFriendRequest(&windows[i], public_key, data, length);
68 }
69}
70
71void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata)
72{
73 int i;
74 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
75 if (windows[i].onMessage != NULL)
76 windows[i].onMessage(&windows[i], m, friendnumber, string, length);
77 }
78}
79
80void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata)
81{
82 int i;
83 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
84 if (windows[i].onAction != NULL)
85 windows[i].onAction(&windows[i], m, friendnumber, string, length);
86 }
87}
88
89void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata)
90{
91 wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string);
92 int i;
93 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
94 if (windows[i].onNickChange != NULL)
95 windows[i].onNickChange(&windows[i], friendnumber, string, length);
96 }
97}
98
99void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata)
100{
101 wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string);
102 int i;
103 for (i=0; i<MAX_WINDOW_SLOTS; ++i) {
104 if (windows[i].onStatusChange != NULL)
105 windows[i].onStatusChange(&windows[i], friendnumber, string, length);
106 }
107}
108
109void on_friendadded(int friendnumber)
110{ 30{
111 friendlist_onFriendAdded(m, friendnumber); 31 endwin();
112 int st; 32 refresh();
113 if ((st = store_data(DATA_FILE)) != 0) { 33 clear();
114 wprintw(prompt->window, "\nCould not store messenger, error code: %d\n", st);
115 }
116} 34}
117/* CALLBACKS END */
118 35
119static void init_term() 36static void init_term()
120{ 37{
121 /* Setup terminal */ 38 /* Setup terminal */
39 signal(SIGWINCH, on_window_resize);
122 initscr(); 40 initscr();
123 cbreak(); 41 cbreak();
124 keypad(stdscr, 1); 42 keypad(stdscr, 1);
@@ -136,10 +54,10 @@ static void init_term()
136 refresh(); 54 refresh();
137} 55}
138 56
139static void init_tox() 57static Messenger *init_tox()
140{ 58{
141 /* Init core */ 59 /* Init core */
142 m = initMessenger(); 60 Messenger *m = initMessenger();
143 61
144 /* Callbacks */ 62 /* Callbacks */
145 m_callback_friendrequest(m, on_request, NULL); 63 m_callback_friendrequest(m, on_request, NULL);
@@ -154,6 +72,7 @@ static void init_tox()
154#else 72#else
155 setname(m, (uint8_t*) "Hipster", sizeof("Hipster")); 73 setname(m, (uint8_t*) "Hipster", sizeof("Hipster"));
156#endif 74#endif
75 return m;
157} 76}
158 77
159#define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */ 78#define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */
@@ -202,67 +121,7 @@ int init_connection(void)
202 return 0; 121 return 0;
203} 122}
204 123
205void init_window_status() 124static void do_tox(Messenger *m, ToxWindow * prompt)
206{
207 /* Default window values decrement from -2 */
208 int i;
209 for (i = 0; i < N_DEFAULT_WINS; ++i)
210 WINDOW_STATUS[i] = -(i+2);
211
212 int j;
213 for (j = N_DEFAULT_WINS; j < MAX_WINDOW_SLOTS; j++)
214 WINDOW_STATUS[j] = -1;
215}
216
217int add_window(ToxWindow w, int n)
218{
219 if (w_num >= TOXWINDOWS_MAX_NUM)
220 return -1;
221
222 if (LINES < 2)
223 return -1;
224
225 w.window = newwin(LINES - 2, COLS, 0, 0);
226 if (w.window == NULL)
227 return -1;
228
229 windows[n] = w;
230 w.onInit(&w, m);
231 w_num++;
232 return n;
233}
234
235/* Deletes window w and cleans up */
236void del_window(ToxWindow *w, int f_num)
237{
238 delwin(w->window);
239 int i;
240 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
241 if (WINDOW_STATUS[i] == f_num) {
242 WINDOW_STATUS[i] = -1;
243 disable_chatwin(f_num);
244 break;
245 }
246 }
247 clear();
248 refresh();
249}
250
251static void init_windows()
252{
253 w_num = 0;
254 int n_prompt = 0;
255 int n_friendslist = 1;
256 if (add_window(new_prompt(), n_prompt) == -1
257 || add_window(new_friendlist(), n_friendslist) == -1) {
258 fprintf(stderr, "add_window() failed.\n");
259 endwin();
260 exit(1);
261 }
262 prompt = &windows[n_prompt];
263}
264
265static void do_tox()
266{ 125{
267 static int conn_try = 0; 126 static int conn_try = 0;
268 static int conn_err = 0; 127 static int conn_err = 0;
@@ -286,190 +145,69 @@ static void do_tox()
286 doMessenger(m); 145 doMessenger(m);
287} 146}
288 147
289static void populate_friends() 148static void load_data(Messenger *m, char *path)
290{ 149{
291 wprintw(prompt->window, "Populating friends...\n"); 150 FILE *fd;
292 uint32_t i; 151 size_t len;
293 for (i = 0; i < m->numfriends; i++) { 152 uint8_t *buf;
294 wprintw(prompt->window, "Added friend %d\n", i);
295 friendlist_onFriendAdded(m, i);
296 }
297}
298 153
299/* 154 if ((fd = fopen(path, "r")) != NULL) {
300 * Store Messenger data to path 155 fseek(fd, 0, SEEK_END);
301 * Return 0 Messenger stored successfully 156 len = ftell(fd);
302 * Return 1 malloc failed 157 fseek(fd, 0, SEEK_SET);
303 * Return 2 fopen failed
304 * Return 3 fwrite failed
305 */
306static int store_data(char *path)
307{
308 FILE *fd;
309 size_t len;
310 uint8_t *buf;
311 158
159 buf = malloc(len);
160 if (buf == NULL) {
161 fprintf(stderr, "malloc() failed.\n");
162 fclose(fd);
163 endwin();
164 exit(1);
165 }
166 if (fread(buf, len, 1, fd) != 1){
167 fprintf(stderr, "fread() failed.\n");
168 free(buf);
169 fclose(fd);
170 endwin();
171 exit(1);
172 }
173 Messenger_load(m, buf, len);
174 }
175 else {
312 len = Messenger_size(m); 176 len = Messenger_size(m);
313 buf = malloc(len); 177 buf = malloc(len);
314 if (buf == NULL) { 178 if (buf == NULL) {
315 return 1; 179 fprintf(stderr, "malloc() failed.\n");
180 endwin();
181 exit(1);
316 } 182 }
317 Messenger_save(m, buf); 183 Messenger_save(m, buf);
318 184
319 fd = fopen(path, "w"); 185 fd = fopen(path, "w");
320 if (fd == NULL) { 186 if (fd == NULL) {
321 free(buf); 187 fprintf(stderr, "fopen() failed.\n");
322 return 2; 188 free(buf);
323 } 189 endwin();
324 190 exit(1);
325 if (fwrite(buf, len, 1, fd) != 1) {
326 free(buf);
327 fclose(fd);
328 return 3;
329 }
330
331 free(buf);
332 fclose(fd);
333
334 wprintw(prompt->window, "Messenger stored\n");
335
336 return 0;
337}
338
339static void load_data(char *path) {
340 FILE *fd;
341 size_t len;
342 uint8_t *buf;
343
344 if ((fd = fopen(path, "r")) != NULL) {
345 fseek(fd, 0, SEEK_END);
346 len = ftell(fd);
347 fseek(fd, 0, SEEK_SET);
348
349 buf = malloc(len);
350 if (buf == NULL) {
351 fprintf(stderr, "malloc() failed.\n");
352 fclose(fd);
353 endwin();
354 exit(1);
355 }
356 if (fread(buf, len, 1, fd) != 1) {
357 fprintf(stderr, "fread() failed.\n");
358 free(buf);
359 fclose(fd);
360 endwin();
361 exit(1);
362 }
363 if (Messenger_load(m, buf, len) != 0) {
364 fprintf(stderr, "Problem while loading messenger");
365 }
366 free(buf);
367 fclose(fd);
368 } else {
369 int st;
370 if ((st = store_data(path)) != 0) {
371 fprintf(stderr, "storing messenger failed with error code: %d", st);
372 endwin();
373 exit(1);
374 }
375 }
376}
377
378static void draw_bar()
379{
380 static int odd = 0;
381 int blinkrate = 30;
382
383 attron(COLOR_PAIR(4));
384 mvhline(LINES - 2, 0, '_', COLS);
385 attroff(COLOR_PAIR(4));
386
387 move(LINES - 1, 0);
388
389 attron(COLOR_PAIR(4) | A_BOLD);
390 printw(" TOXIC " TOXICVER "|");
391 attroff(COLOR_PAIR(4) | A_BOLD);
392
393 int i;
394 for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) {
395 if (WINDOW_STATUS[i] != -1) {
396 if (i == active_window)
397 attron(A_BOLD);
398
399 odd = (odd+1) % blinkrate;
400 if (windows[i].blink && (odd < (blinkrate/2)))
401 attron(COLOR_PAIR(3));
402
403 printw(" %s", windows[i].title);
404 if (windows[i].blink && (odd < (blinkrate/2)))
405 attroff(COLOR_PAIR(3));
406
407 if (i == active_window) {
408 attroff(A_BOLD);
409 }
410 } 191 }
411 }
412 refresh();
413}
414 192
415void prepare_window(WINDOW *w) 193 if (fwrite(buf, len, 1, fd) != 1){
416{ 194 fprintf(stderr, "fwrite() failed.\n");
417 mvwin(w, 0, 0); 195 free(buf);
418 wresize(w, LINES-2, COLS); 196 fclose(fd);
419} 197 endwin();
420 198 exit(1);
421/* Shows next window when tab or back-tab is pressed */
422void set_active_window(int ch)
423{
424 int f_inf = 0;
425 int max = MAX_WINDOW_SLOTS-1;
426 if (ch == '\t') {
427 int i = (active_window + 1) % max;
428 while (true) {
429 if (WINDOW_STATUS[i] != -1) {
430 active_window = i;
431 return;
432 }
433 i = (i + 1) % max;
434 if (f_inf++ > max) { // infinite loop check
435 endwin();
436 exit(2);
437 }
438 }
439 }else {
440 int i = active_window - 1;
441 if (i < 0) i = max;
442 while (true) {
443 if (WINDOW_STATUS[i] != -1) {
444 active_window = i;
445 return;
446 }
447 if (--i < 0) i = max;
448 if (f_inf++ > max) {
449 endwin();
450 exit(2);
451 }
452 } 199 }
453 } 200 }
201 free(buf);
202 fclose(fd);
454} 203}
455 204
456int main(int argc, char *argv[]) 205int main(int argc, char *argv[])
457{ 206{
458 int ch;
459 ToxWindow* a;
460 char *user_config_dir = get_user_config_dir(); 207 char *user_config_dir = get_user_config_dir();
461 int config_err = create_user_config_dir(user_config_dir); 208 char *DATA_FILE = NULL;
462 if(config_err) { 209 int config_err = 0;
463 DATA_FILE = "data";
464 } else {
465 DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1);
466 strcpy(DATA_FILE, user_config_dir);
467 strcat(DATA_FILE, CONFIGDIR);
468 strcat(DATA_FILE, "data");
469 }
470 free(user_config_dir);
471 210
472 /* This is broken */
473 int f_loadfromfile = 1; 211 int f_loadfromfile = 1;
474 int f_flag = 0; 212 int f_flag = 0;
475 int i = 0; 213 int i = 0;
@@ -479,7 +217,7 @@ int main(int argc, char *argv[])
479 else if (argv[i][0] == '-') { 217 else if (argv[i][0] == '-') {
480 if (argv[i][1] == 'f') { 218 if (argv[i][1] == 'f') {
481 if (argv[i + 1] != NULL) 219 if (argv[i + 1] != NULL)
482 DATA_FILE = argv[i + 1]; 220 DATA_FILE = strdup(argv[i + 1]);
483 else 221 else
484 f_flag = -1; 222 f_flag = -1;
485 } else if (argv[i][1] == 'n') { 223 } else if (argv[i][1] == 'n') {
@@ -488,15 +226,27 @@ int main(int argc, char *argv[])
488 } 226 }
489 } 227 }
490 228
229 if (DATA_FILE == NULL ) {
230 config_err = create_user_config_dir(user_config_dir);
231 if (config_err) {
232 DATA_FILE = strdup("data");
233 } else {
234 DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1);
235 strcpy(DATA_FILE, user_config_dir);
236 strcat(DATA_FILE, CONFIGDIR);
237 strcat(DATA_FILE, "data");
238 }
239 }
240 free(user_config_dir);
241
491 init_term(); 242 init_term();
492 init_tox(); 243 Messenger *m = init_tox();
493 init_windows(); 244 ToxWindow *prompt = init_windows(m);
494 init_window_status(); 245 init_window_status();
495 246
496 if(f_loadfromfile) { 247 if(f_loadfromfile)
497 load_data(DATA_FILE); 248 load_data(m, DATA_FILE);
498 populate_friends(); 249 free(DATA_FILE);
499 }
500 250
501 if (f_flag == -1) { 251 if (f_flag == -1) {
502 attron(COLOR_PAIR(3) | A_BOLD); 252 attron(COLOR_PAIR(3) | A_BOLD);
@@ -513,25 +263,11 @@ int main(int argc, char *argv[])
513 } 263 }
514 while(true) { 264 while(true) {
515 /* Update tox */ 265 /* Update tox */
516 do_tox(); 266 do_tox(m, prompt);
517 267
518 /* Draw */ 268 /* Draw */
519 a = &windows[active_window]; 269 draw_active_window(m);
520 prepare_window(a->window);
521 a->blink = false;
522 draw_bar();
523 a->onDraw(a);
524
525 /* Handle input */
526 ch = getch();
527 if (ch == '\t' || ch == KEY_BTAB)
528 set_active_window(ch);
529 else if (ch != ERR)
530 a->onKey(a, m, ch);
531 } 270 }
532
533 cleanupMessenger(m); 271 cleanupMessenger(m);
534 free(DATA_FILE);
535
536 return 0; 272 return 0;
537} 273}
diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c
index e1a7d75c..b84773af 100644
--- a/testing/toxic/prompt.c
+++ b/testing/toxic/prompt.c
@@ -11,11 +11,12 @@
11#include "../../core/network.h" 11#include "../../core/network.h"
12 12
13#include "windows.h" 13#include "windows.h"
14#include "prompt.h"
14 15
15uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX 16uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX
16uint8_t num_requests=0; // XXX 17uint8_t num_requests=0; // XXX
17 18
18extern void on_friendadded(int friendnumber); 19static friendAddedFn *on_friendadded;
19static char prompt_buf[MAX_STR_SIZE] = {0}; 20static char prompt_buf[MAX_STR_SIZE] = {0};
20static int prompt_buf_pos = 0; 21static int prompt_buf_pos = 0;
21 22
@@ -87,7 +88,7 @@ void cmd_accept(ToxWindow *self, Messenger *m, char **args)
87 wprintw(self->window, "Failed to add friend.\n"); 88 wprintw(self->window, "Failed to add friend.\n");
88 else { 89 else {
89 wprintw(self->window, "Friend accepted as: %d.\n", num); 90 wprintw(self->window, "Friend accepted as: %d.\n", num);
90 on_friendadded(num); 91 on_friendadded(m, num);
91 } 92 }
92} 93}
93 94
@@ -121,6 +122,11 @@ void cmd_add(ToxWindow *self, Messenger *m, char **args)
121 } 122 }
122 id_bin[i] = x; 123 id_bin[i] = x;
123 } 124 }
125
126 for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) {
127 id[i] = toupper(id[i]);
128 }
129
124 int num = m_addfriend(m, id_bin, (uint8_t*) msg, strlen(msg)+1); 130 int num = m_addfriend(m, id_bin, (uint8_t*) msg, strlen(msg)+1);
125 switch (num) { 131 switch (num) {
126 case FAERR_TOOLONG: 132 case FAERR_TOOLONG:
@@ -138,9 +144,15 @@ void cmd_add(ToxWindow *self, Messenger *m, char **args)
138 case FAERR_UNKNOWN: 144 case FAERR_UNKNOWN:
139 wprintw(self->window, "Undefined error when adding friend.\n"); 145 wprintw(self->window, "Undefined error when adding friend.\n");
140 break; 146 break;
147 case FAERR_BADCHECKSUM:
148 wprintw(self->window, "Bad checksum in address.\n");
149 break;
150 case FAERR_SETNEWNOSPAM:
151 wprintw(self->window, "Nospam was different.\n");
152 break;
141 default: 153 default:
142 wprintw(self->window, "Friend added as %d.\n", num); 154 wprintw(self->window, "Friend added as %d.\n", num);
143 on_friendadded(num); 155 on_friendadded(m, num);
144 break; 156 break;
145 } 157 }
146} 158}
@@ -226,7 +238,7 @@ void cmd_myid(ToxWindow *self, Messenger *m, char **args)
226 snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); 238 snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff);
227 strcat(id, xx); 239 strcat(id, xx);
228 } 240 }
229 wprintw(self->window, "Your ID: %s\n", id); 241 wprintw(self->window, "%s\n", id);
230} 242}
231 243
232void cmd_nick(ToxWindow *self, Messenger *m, char **args) 244void cmd_nick(ToxWindow *self, Messenger *m, char **args)
@@ -422,8 +434,9 @@ static void prompt_onInit(ToxWindow *self, Messenger *m)
422 wclrtoeol(self->window); 434 wclrtoeol(self->window);
423} 435}
424 436
425ToxWindow new_prompt() 437ToxWindow new_prompt(friendAddedFn *f)
426{ 438{
439 on_friendadded = f;
427 ToxWindow ret; 440 ToxWindow ret;
428 memset(&ret, 0, sizeof(ret)); 441 memset(&ret, 0, sizeof(ret));
429 ret.onKey = &prompt_onKey; 442 ret.onKey = &prompt_onKey;
diff --git a/testing/toxic/prompt.h b/testing/toxic/prompt.h
new file mode 100644
index 00000000..6c5320ab
--- /dev/null
+++ b/testing/toxic/prompt.h
@@ -0,0 +1,14 @@
1#ifndef PROMPT_H_UZYGWFFL
2#define PROMPT_H_UZYGWFFL
3
4#include "windows.h"
5
6typedef void (friendAddedFn)(Messenger *m, int friendnumber);
7
8ToxWindow new_prompt(friendAddedFn *f);
9int add_req(uint8_t *public_key);
10unsigned char *hex_string_to_bin(char hex_string[]);
11
12#endif /* end of include guard: PROMPT_H_UZYGWFFL */
13
14
diff --git a/testing/toxic/windows.c b/testing/toxic/windows.c
new file mode 100644
index 00000000..6de50741
--- /dev/null
+++ b/testing/toxic/windows.c
@@ -0,0 +1,239 @@
1#include "friendlist.h"
2#include "prompt.h"
3#include "dhtstatus.h"
4#include "windows.h"
5
6/* Holds status of chat windows */
7char WINDOW_STATUS[MAX_WINDOW_SLOTS];
8
9static int w_num;
10static ToxWindow windows[MAX_WINDOW_SLOTS];
11static Messenger *m;
12int active_window;
13
14static ToxWindow* prompt;
15
16/* CALLBACKS START */
17void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void* userdata)
18{
19 int n = add_req(public_key);
20 wprintw(prompt->window, "\nFriend request from:\n");
21
22 int i;
23 for (i = 0; i < KEY_SIZE_BYTES; ++i) {
24 wprintw(prompt->window, "%02x", public_key[i] & 0xff);
25 }
26
27 wprintw(prompt->window, "\nWith the message: %s\n", data);
28 wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n);
29
30 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
31 if (windows[i].onFriendRequest != NULL)
32 windows[i].onFriendRequest(&windows[i], public_key, data, length);
33 }
34}
35
36void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata)
37{
38 int i;
39 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
40 if (windows[i].onMessage != NULL)
41 windows[i].onMessage(&windows[i], m, friendnumber, string, length);
42 }
43}
44
45void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata)
46{
47 int i;
48 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
49 if (windows[i].onAction != NULL)
50 windows[i].onAction(&windows[i], m, friendnumber, string, length);
51 }
52}
53
54void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata)
55{
56 wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string);
57 int i;
58 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
59 if (windows[i].onNickChange != NULL)
60 windows[i].onNickChange(&windows[i], friendnumber, string, length);
61 }
62}
63
64void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata)
65{
66 wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string);
67 int i;
68 for (i=0; i<MAX_WINDOW_SLOTS; ++i) {
69 if (windows[i].onStatusChange != NULL)
70 windows[i].onStatusChange(&windows[i], friendnumber, string, length);
71 }
72}
73
74void on_friendadded(Messenger *m, int friendnumber)
75{
76 friendlist_onFriendAdded(m, friendnumber);
77}
78/* CALLBACKS END */
79
80int add_window(Messenger *m, ToxWindow w, int n)
81{
82 if (w_num >= TOXWINDOWS_MAX_NUM)
83 return -1;
84
85 if (LINES < 2)
86 return -1;
87
88 w.window = newwin(LINES - 2, COLS, 0, 0);
89 if (w.window == NULL)
90 return -1;
91
92 windows[n] = w;
93 w.onInit(&w, m);
94 w_num++;
95 active_window = n;
96 return n;
97}
98
99/* Deletes window w and cleans up */
100void del_window(ToxWindow *w, int f_num)
101{
102 active_window = 0; // Go to prompt screen
103 delwin(w->window);
104 int i;
105 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
106 if (WINDOW_STATUS[i] == f_num) {
107 WINDOW_STATUS[i] = -1;
108 disable_chatwin(f_num);
109 break;
110 }
111 }
112 clear();
113 refresh();
114}
115
116/* Shows next window when tab or back-tab is pressed */
117void set_active_window(int ch)
118{
119 int f_inf = 0;
120 int max = MAX_WINDOW_SLOTS-1;
121 if (ch == '\t') {
122 int i = (active_window + 1) % max;
123 while (true) {
124 if (WINDOW_STATUS[i] != -1) {
125 active_window = i;
126 return;
127 }
128 i = (i + 1) % max;
129 if (f_inf++ > max) { // infinite loop check
130 endwin();
131 exit(2);
132 }
133 }
134 }else {
135 int i = active_window - 1;
136 if (i < 0) i = max;
137 while (true) {
138 if (WINDOW_STATUS[i] != -1) {
139 active_window = i;
140 return;
141 }
142 if (--i < 0) i = max;
143 if (f_inf++ > max) {
144 endwin();
145 exit(2);
146 }
147 }
148 }
149}
150
151void init_window_status()
152{
153 /* Default window values decrement from -2 */
154 int i;
155 for (i = 0; i < N_DEFAULT_WINS; ++i)
156 WINDOW_STATUS[i] = -(i+2);
157
158 int j;
159 for (j = N_DEFAULT_WINS; j < MAX_WINDOW_SLOTS; j++)
160 WINDOW_STATUS[j] = -1;
161}
162
163ToxWindow *init_windows()
164{
165 w_num = 0;
166 int n_prompt = 0;
167 int n_friendslist = 1;
168 int n_dhtstatus = 2;
169 if (add_window(m, new_prompt(on_friendadded), n_prompt) == -1
170 || add_window(m, new_friendlist(WINDOW_STATUS), n_friendslist) == -1
171 || add_window(m, new_dhtstatus(), n_dhtstatus) == -1) {
172 fprintf(stderr, "add_window() failed.\n");
173 endwin();
174 exit(1);
175 }
176 active_window = n_prompt;
177 prompt = &windows[n_prompt];
178 return prompt;
179}
180
181static void draw_bar()
182{
183 static int odd = 0;
184 int blinkrate = 30;
185
186 attron(COLOR_PAIR(4));
187 mvhline(LINES - 2, 0, '_', COLS);
188 attroff(COLOR_PAIR(4));
189
190 move(LINES - 1, 0);
191
192 attron(COLOR_PAIR(4) | A_BOLD);
193 printw(" TOXIC " TOXICVER "|");
194 attroff(COLOR_PAIR(4) | A_BOLD);
195
196 int i;
197 for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) {
198 if (WINDOW_STATUS[i] != -1) {
199 if (i == active_window)
200 attron(A_BOLD);
201
202 odd = (odd+1) % blinkrate;
203 if (windows[i].blink && (odd < (blinkrate/2)))
204 attron(COLOR_PAIR(3));
205
206 printw(" %s", windows[i].title);
207 if (windows[i].blink && (odd < (blinkrate/2)))
208 attroff(COLOR_PAIR(3));
209
210 if (i == active_window) {
211 attroff(A_BOLD);
212 }
213 }
214 }
215 refresh();
216}
217
218void prepare_window(WINDOW *w)
219{
220 mvwin(w, 0, 0);
221 wresize(w, LINES-2, COLS);
222}
223
224void draw_active_window(Messenger *m)
225{
226
227 ToxWindow *a = &windows[active_window];
228 prepare_window(a->window);
229 a->blink = false;
230 draw_bar();
231 a->onDraw(a);
232
233 /* Handle input */
234 int ch = getch();
235 if (ch == '\t' || ch == KEY_BTAB)
236 set_active_window(ch);
237 else if (ch != ERR)
238 a->onKey(a, m, ch);
239}
diff --git a/testing/toxic/windows.h b/testing/toxic/windows.h
index 648243d0..893ccf6f 100644
--- a/testing/toxic/windows.h
+++ b/testing/toxic/windows.h
@@ -1,19 +1,28 @@
1/* 1/*
2 * Toxic -- Tox Curses Client 2 * Toxic -- Tox Curses Client
3 */ 3 */
4#ifndef _windows_h
5#define _windows_h
4 6
7#include <curses.h>
8#include <stdint.h>
5#include <stdbool.h> 9#include <stdbool.h>
10#include "../../core/Messenger.h"
6#define TOXWINDOWS_MAX_NUM 32 11#define TOXWINDOWS_MAX_NUM 32
7#define MAX_FRIENDS_NUM 100 12#define MAX_FRIENDS_NUM 100
8#define MAX_STR_SIZE 256 13#define MAX_STR_SIZE 256
9#define KEY_SIZE_BYTES 32 14#define KEY_SIZE_BYTES 32
10 15
11/* number of permanent default windows */ 16/* number of permanent default windows */
12#define N_DEFAULT_WINS 2 17#define N_DEFAULT_WINS 3
13 18
14/* maximum window slots for WINDOW_STATUS array */ 19/* maximum window slots for WINDOW_STATUS array */
15#define MAX_WINDOW_SLOTS N_DEFAULT_WINS+MAX_FRIENDS_NUM 20#define MAX_WINDOW_SLOTS N_DEFAULT_WINS+MAX_FRIENDS_NUM
16 21
22#ifndef TOXICVER
23#define TOXICVER "NOVER" //Use the -D flag to set this
24#endif
25
17typedef struct ToxWindow_ ToxWindow; 26typedef struct ToxWindow_ ToxWindow;
18 27
19struct ToxWindow_ { 28struct ToxWindow_ {
@@ -32,3 +41,17 @@ struct ToxWindow_ {
32 41
33 WINDOW* window; 42 WINDOW* window;
34}; 43};
44
45void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void* userdata);
46void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata);
47void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata);
48void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata);
49void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata);
50void init_window_status();
51ToxWindow * init_windows();
52void draw_active_window(Messenger * m);
53int add_window(Messenger *m, ToxWindow w, int n);
54void del_window(ToxWindow *w, int f_num);
55void set_active_window(int ch);
56#endif
57