diff options
author | charmlesscoin <charmlesscoin@gmail.com> | 2013-08-06 20:58:42 -0400 |
---|---|---|
committer | charmlesscoin <charmlesscoin@gmail.com> | 2013-08-06 20:58:42 -0400 |
commit | c644ccd28782e9d74f5962a97a0973551fb7afe2 (patch) | |
tree | 42f892aea55a6394d5d6ff0dbace2214675cbd71 | |
parent | 95a3f69580749b8fcabf92cc2ace757d61fa34de (diff) | |
parent | d04f2d0e51931db5fbd8c672c44bb1e59fc58b79 (diff) |
Merge branch 'master' of git://github.com/irungentoo/ProjectTox-Core
-rw-r--r-- | cmake/FindLIBCONFIG.cmake | 7 | ||||
-rw-r--r-- | core/DHT.c | 142 | ||||
-rw-r--r-- | core/DHT.h | 2 | ||||
-rw-r--r-- | core/LAN_discovery.c | 4 | ||||
-rw-r--r-- | core/Messenger.c | 6 | ||||
-rw-r--r-- | core/packets.h | 37 | ||||
-rw-r--r-- | core/ping.c | 127 | ||||
-rw-r--r-- | core/ping.h | 5 | ||||
-rw-r--r-- | core/util.c | 13 | ||||
-rw-r--r-- | core/util.h | 3 | ||||
-rw-r--r-- | testing/misc_tools.c | 12 | ||||
-rw-r--r-- | testing/misc_tools.h | 142 | ||||
-rw-r--r-- | testing/nTox.c | 2 | ||||
-rw-r--r-- | testing/toxic/chat.c | 120 | ||||
-rw-r--r-- | testing/toxic/friendlist.c | 142 | ||||
-rw-r--r-- | testing/toxic/main.c | 321 | ||||
-rw-r--r-- | testing/toxic/prompt.c | 238 | ||||
-rw-r--r-- | testing/toxic/windows.h | 8 |
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 | ||
8 | FIND_PATH(LIBCONFIG_INCLUDE_DIR NAMES libconfig.h) | 8 | if (UNIX) |
9 | find_package(PkgConfig QUIET) | ||
10 | pkg_check_modules(_LIBCONFIG QUIET libconfig) | ||
11 | endif () | ||
12 | |||
13 | FIND_PATH(LIBCONFIG_INCLUDE_DIR NAMES libconfig.h HINTS ${_LIBCONFIG_INCLUDEDIR}) | ||
9 | 14 | ||
10 | FIND_LIBRARY(LIBCONFIG_LIBRARY NAMES config) | 15 | FIND_LIBRARY(LIBCONFIG_LIBRARY NAMES config) |
11 | 16 | ||
@@ -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 | */ |
354 | static void addto_lists(IP_Port ip_port, uint8_t * client_id) | 355 | void 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 | */ | ||
478 | static 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 */ | ||
512 | static 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 */ |
541 | static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) | 477 | static 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 | */ | ||
624 | static 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 | |||
650 | static 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 | |||
677 | static int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source) | 557 | static 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); |
@@ -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 */ |
105 | int DHT_isconnected(); | 105 | int DHT_isconnected(); |
106 | 106 | ||
107 | void 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 | |||
8 | typedef struct { | ||
9 | uint8_t id[CLIENT_ID_SIZE]; | ||
10 | |||
11 | } __attribute__((packed)) clientid_t; | ||
12 | |||
13 | typedef enum { | ||
14 | PACKET_PING_REQ = 0, | ||
15 | PACKET_PING_RES = 1 | ||
16 | |||
17 | } packetid_t; | ||
18 | |||
19 | // Ping packet | ||
20 | typedef 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 | ||
30 | typedef 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 | ||
23 | static pinged_t pings[PING_NUM_MAX]; | 26 | static pinged_t pings[PING_NUM_MAX]; |
24 | static size_t num_pings; | 27 | static size_t num_pings; |
25 | static size_t pos_pings; | 28 | static size_t pos_pings; |
29 | static clientid_t* self_id = (clientid_t*) &self_public_key; | ||
26 | 30 | ||
31 | extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; // DHT.c | ||
27 | 32 | ||
28 | void init_ping() | 33 | void 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 | ||
62 | uint64_t add_ping(IP_Port ipp) // O(n) | 68 | uint64_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 | |||
112 | int 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 | |||
141 | int 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 | |||
166 | int 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 | |||
193 | int 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 @@ | |||
10 | void init_ping(); | 10 | void init_ping(); |
11 | uint64_t add_ping(IP_Port ipp); | 11 | uint64_t add_ping(IP_Port ipp); |
12 | bool is_pinging(IP_Port ipp, uint64_t ping_id); | 12 | bool is_pinging(IP_Port ipp, uint64_t ping_id); |
13 | 13 | int send_ping_request(IP_Port ipp, clientid_t* client_id); | |
14 | int send_ping_response(IP_Port ipp, clientid_t* client_id, uint64_t ping_id); | ||
15 | int handle_ping_request(uint8_t* packet, uint32_t length, IP_Port source); | ||
16 | int 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 | ||
14 | uint64_t now() | 15 | uint64_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 | |||
37 | bool id_eq(clientid_t* dest, clientid_t* src) | ||
38 | { | ||
39 | return memcmp(dest, src, sizeof(clientid_t)) == 0; | ||
40 | } | ||
41 | |||
42 | void 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 @@ | |||
8 | uint64_t now(); | 8 | uint64_t now(); |
9 | uint64_t random_64b(); | 9 | uint64_t random_64b(); |
10 | bool ipp_eq(IP_Port a, IP_Port b); | 10 | bool ipp_eq(IP_Port a, IP_Port b); |
11 | bool id_eq(clientid_t* dest, clientid_t* src); | ||
12 | void 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 */ |
31 | unsigned char * hex_string_to_bin(char hex_string[]) | 35 | unsigned 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 | ||
27 | unsigned char * hex_string_to_bin(char hex_string[]); | 27 | unsigned 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 | |||
75 | This sample program makes a new struct which contains a | ||
76 | character and a tox_list_t. It then prompts a user for | ||
77 | input until he enters q or e. It then adds each character | ||
78 | to the list, and uses a special for loop to print them. | ||
79 | It then removes all the 'z' characters, and prints the list | ||
80 | again. | ||
81 | |||
82 | //Notice that the data to be put in the list *contains* tox_list_t; | ||
83 | //usually, this is the other way around! | ||
84 | typedef 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 | |||
89 | int 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 | |||
103 | TOX_LIST_FOR_EACH() takes a struct tox_list and a name for a temporary pointer to use in the loop. | ||
104 | |||
105 | TOX_LIST_GET_VALUE() uses magic to return an instance of a structure that contains tox_list_t. | ||
106 | You have to give it a temporary tox_string_t, name of tox_list_t member inside our structure (tox_lst), | ||
107 | and 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 | |||
141 | typedef struct tox_list { | ||
142 | struct tox_list *prev, *next; | ||
143 | } tox_list_t; | ||
144 | |||
145 | /* Returns a new tox_list_t. */ | ||
146 | static 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. */ | ||
151 | static 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 | |||
161 | static 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 | ||
415 | FILE_ERROR: | 417 | FILE_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 | ||
17 | typedef struct { | 17 | typedef 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 | ||
28 | extern void fix_name(uint8_t* name); | 25 | extern int active_window; |
29 | void print_help(ChatContext* self); | ||
30 | void execute(ToxWindow* self, ChatContext* ctx, char* cmd); | ||
31 | 26 | ||
32 | static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) { | 27 | extern void del_window(ToxWindow *w, int f_num); |
33 | ChatContext* ctx = (ChatContext*) self->x; | 28 | extern void fix_name(uint8_t *name); |
29 | void print_help(ChatContext *self); | ||
30 | void execute(ToxWindow *self, ChatContext *ctx, char *cmd); | ||
31 | |||
32 | static 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 | ||
65 | static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t len) { | 63 | static 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 | ||
81 | static void chat_onStatusChange(ToxWindow* self, int num, uint8_t* status, uint16_t len) { | 78 | static 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 | ||
97 | static void chat_onKey(ToxWindow* self, int key) { | 93 | static 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 | ||
146 | void execute(ToxWindow* self, ChatContext* ctx, char* cmd) | 142 | void 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 | ||
194 | static void chat_onDraw(ToxWindow* self) { | 203 | static 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 | ||
212 | static void chat_onInit(ToxWindow* self) { | 218 | static 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 | ||
224 | void print_help(ChatContext* self) { | 229 | void 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 | ||
239 | ToxWindow new_chat(int friendnum) { | 246 | ToxWindow 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 | ||
15 | extern int add_window(ToxWindow w); | 15 | extern char WINDOW_STATUS[TOXWINDOWS_MAX_NUM]; |
16 | extern int focus_window(int num); | 16 | extern int add_window(ToxWindow w, int n); |
17 | extern ToxWindow new_chat(int friendnum); | 17 | extern ToxWindow new_chat(int friendnum); |
18 | 18 | ||
19 | #define MAX_FRIENDS_NUM 100 | 19 | extern int active_window; |
20 | 20 | ||
21 | typedef struct { | 21 | typedef 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 | ||
28 | static friend_t friends[MAX_FRIENDS_NUM]; | 28 | static friend_t friends[MAX_FRIENDS_NUM]; |
29 | static int num_friends = 0; | 29 | static int num_friends = 0; |
30 | static int num_selected = 0; | 30 | static int num_selected = 0; |
31 | 31 | ||
32 | 32 | void fix_name(uint8_t *name) | |
33 | void 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 | ||
50 | void friendlist_onMessage(ToxWindow* self, int num, uint8_t* str, uint16_t len) { | 45 | void 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 | ||
60 | void friendlist_onNickChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) { | 65 | void 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 | ||
70 | void friendlist_onStatusChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) { | 75 | void 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 | ||
80 | int friendlist_onFriendAdded(int num) { | 85 | int 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 | ||
95 | static void friendlist_onKey(ToxWindow* self, int key) { | 98 | static 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 | ||
115 | static void friendlist_onDraw(ToxWindow* self) { | 133 | static 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 | ||
148 | static void friendlist_onInit(ToxWindow* self) { | 162 | void disable_chatwin(int f_num) |
149 | 163 | { | |
164 | friends[f_num].chatwin = -1; | ||
150 | } | 165 | } |
151 | 166 | ||
167 | static void friendlist_onInit(ToxWindow *self) | ||
168 | { | ||
169 | |||
170 | } | ||
152 | 171 | ||
153 | ToxWindow new_friendlist() { | 172 | ToxWindow 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(); | |||
17 | extern ToxWindow new_friendlist(); | 17 | extern ToxWindow new_friendlist(); |
18 | 18 | ||
19 | extern int friendlist_onFriendAdded(int num); | 19 | extern int friendlist_onFriendAdded(int num); |
20 | extern void disable_chatwin(int f_num); | ||
21 | extern int add_req(uint8_t *public_key); // XXX | ||
20 | 22 | ||
21 | extern int add_req(uint8_t* public_key); // XXX | 23 | /* Holds status of chat windows */ |
24 | char WINDOW_STATUS[MAX_WINDOW_SLOTS]; | ||
22 | 25 | ||
23 | #define TOXWINDOWS_MAX_NUM 32 | 26 | static ToxWindow windows[MAX_WINDOW_SLOTS]; |
24 | |||
25 | static ToxWindow windows[TOXWINDOWS_MAX_NUM]; | ||
26 | static int w_num; | ||
27 | static int w_active; | ||
28 | static ToxWindow* prompt; | 27 | static ToxWindow* prompt; |
29 | 28 | ||
30 | // CALLBACKS START | 29 | int w_num; |
31 | void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) { | 30 | int active_window; |
32 | size_t i; | ||
33 | int n = add_req(public_key); | ||
34 | 31 | ||
32 | /* CALLBACKS START */ | ||
33 | void 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 | ||
50 | void on_message(int friendnumber, uint8_t* string, uint16_t length) { | 51 | void 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 | ||
61 | void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) { | 61 | void 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 | ||
72 | void on_statuschange(int friendnumber, USERSTATUS_KIND kind, uint8_t* string, uint16_t length) { | 71 | void 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 | ||
83 | void on_friendadded(int friendnumber) { | 81 | void on_friendadded(int friendnumber) |
82 | { | ||
84 | friendlist_onFriendAdded(friendnumber); | 83 | friendlist_onFriendAdded(friendnumber); |
85 | } | 84 | } |
86 | // CALLBACKS END | 85 | /* CALLBACKS END */ |
87 | 86 | ||
88 | static void init_term() { | 87 | static 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 | ||
107 | static void init_tox() { | 106 | static 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 | ||
118 | int add_window(ToxWindow w) { | 118 | void 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 | |||
130 | int 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 | ||
136 | int focus_window(int num) { | 148 | /* Deletes window w and cleans up */ |
137 | if(num >= w_num || num < 0) | 149 | void 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 | ||
144 | static void init_windows() { | 164 | static 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 | ||
158 | static void do_tox() { | 178 | static 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 | ||
173 | static void load_data(char *path) { | 192 | static 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 | ||
239 | static void draw_bar() { | 249 | static 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 | ||
278 | void prepare_window(WINDOW* w) { | 286 | void 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 | ||
283 | int main(int argc, char* argv[]) { | 292 | /* Shows next window when tab or back-tab is pressed */ |
293 | void 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 | |||
329 | int 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 | |||
16 | uint8_t num_requests=0; // XXX | 16 | uint8_t num_requests=0; // XXX |
17 | 17 | ||
18 | extern void on_friendadded(int friendnumber); | 18 | extern void on_friendadded(int friendnumber); |
19 | static void print_usage(ToxWindow* self); | 19 | static void print_usage(ToxWindow *self); |
20 | static char prompt_buf[256] = {0}; | ||
21 | static int prompt_buf_pos = 0; | ||
20 | 22 | ||
21 | // XXX: | 23 | // XXX: |
22 | int add_req(uint8_t* public_key) { | 24 | int 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 |
30 | unsigned char * hex_string_to_bin(char hex_string[]) | 32 | unsigned 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 | ||
41 | static char prompt_buf[256] = {0}; | 43 | static void execute(ToxWindow *self, char *u_cmd) |
42 | static int prompt_buf_pos=0; | 44 | { |
43 | 45 | int newlines = 0; | |
44 | static 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 | ||
265 | static void prompt_onKey(ToxWindow* self, int key) { | 244 | static 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 | ||
291 | static void prompt_onDraw(ToxWindow* self) { | 281 | static 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 | ||
308 | static void print_usage(ToxWindow* self) { | 301 | static 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 | ||
330 | static void prompt_onInit(ToxWindow* self) { | 324 | static 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 | ||
337 | ToxWindow new_prompt() { | 331 | ToxWindow 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 | ||
7 | typedef struct ToxWindow_ ToxWindow; | 15 | typedef struct ToxWindow_ ToxWindow; |
8 | 16 | ||