summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--testing/CMakeLists.txt2
-rw-r--r--testing/cmake/toxic.cmake11
-rw-r--r--testing/toxic/main.c229
-rw-r--r--testing/toxic/prompt.c292
-rw-r--r--testing/toxic/windows.h10
5 files changed, 544 insertions, 0 deletions
diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt
index 12efc2f4..3085b0c5 100644
--- a/testing/CMakeLists.txt
+++ b/testing/CMakeLists.txt
@@ -10,4 +10,6 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Lossless_UDP_testserver.cmake)
10include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Messenger_test.cmake) 10include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Messenger_test.cmake)
11if(NOT WIN32) 11if(NOT WIN32)
12 include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nTox.cmake) 12 include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nTox.cmake)
13include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/toxic.cmake)
14
13endif() 15endif()
diff --git a/testing/cmake/toxic.cmake b/testing/cmake/toxic.cmake
new file mode 100644
index 00000000..494dea90
--- /dev/null
+++ b/testing/cmake/toxic.cmake
@@ -0,0 +1,11 @@
1cmake_minimum_required(VERSION 2.6.0)
2project(toxic C)
3
4set(exe_name toxic/toxic)
5
6add_executable(${exe_name}
7 toxic/main.c toxic/prompt.c)
8
9target_link_libraries(${exe_name} curses)
10
11linkCoreLibraries(${exe_name})
diff --git a/testing/toxic/main.c b/testing/toxic/main.c
new file mode 100644
index 00000000..0aad6777
--- /dev/null
+++ b/testing/toxic/main.c
@@ -0,0 +1,229 @@
1/*
2 * Toxic -- Tox Curses Client
3 */
4
5#include <curses.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <stdbool.h>
9#include <stdint.h>
10
11#include "../../core/Messenger.h"
12#include "../../core/network.h"
13
14#include "windows.h"
15
16extern ToxWindow new_prompt();
17extern int add_req(uint8_t* public_key); // XXX
18
19#define TOXWINDOWS_MAX_NUM 32
20
21static ToxWindow windows[TOXWINDOWS_MAX_NUM];
22static int w_num;
23static int w_active;
24static ToxWindow* prompt;
25
26// CALLBACKS START
27void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) {
28 int n = add_req(public_key);
29
30 wprintw(prompt->window, "\nFriend request.\nUse \"accept %d\" to accept it.\n", n);
31}
32
33void on_message(int friendnumber, uint8_t* string, uint16_t length) {
34 wprintw(prompt->window, "\n(message) %d: %s!\n", friendnumber, string);
35}
36
37void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) {
38 wprintw(prompt->window, "\n(nick) %d: %s!\n", friendnumber, string);
39}
40
41void on_statuschange(int friendnumber, uint8_t* string, uint16_t length) {
42 wprintw(prompt->window, "\n(status) %d: %s!\n", friendnumber, string);
43}
44// CALLBACKS END
45
46static void init_term() {
47 // Setup terminal.
48 initscr();
49 cbreak();
50 keypad(stdscr, 1);
51 noecho();
52 timeout(2000);
53
54 if(has_colors()) {
55 start_color();
56 init_pair(1, COLOR_GREEN, COLOR_BLACK);
57 init_pair(2, COLOR_CYAN, COLOR_BLACK);
58 init_pair(3, COLOR_RED, COLOR_BLACK);
59 init_pair(4, COLOR_BLUE, COLOR_BLACK);
60 }
61
62 refresh();
63}
64
65static void init_tox() {
66 // Init core.
67 initMessenger();
68
69 // Callbacks.
70 m_callback_friendrequest(on_request);
71 m_callback_friendmessage(on_message);
72 m_callback_namechange(on_nickchange);
73 m_callback_userstatus(on_statuschange);
74}
75
76static int add_window(ToxWindow w) {
77 if(w_num == TOXWINDOWS_MAX_NUM)
78 return -1;
79
80 if(LINES < 2)
81 return -1;
82
83 w.window = newwin(LINES - 2, COLS, 0, 0);
84
85 if(w.window == NULL)
86 return -1;
87
88 windows[w_num++] = w;
89 w.onInit(&w);
90
91 return w_num;
92}
93
94static void init_windows() {
95 w_num = 0;
96 w_active = 0;
97
98 if(add_window(new_prompt()) == -1) {
99 fprintf(stderr, "add_window() failed.\n");
100
101 endwin();
102 exit(1);
103 }
104
105 prompt = &windows[0];
106}
107
108static void do_tox() {
109 static bool dht_on = false;
110
111 if(!dht_on && DHT_isconnected()) {
112 dht_on = true;
113 wprintw(prompt->window, "\nDHT connected!\n");
114 }
115 else if(dht_on && !DHT_isconnected()) {
116 dht_on = false;
117 wprintw(prompt->window, "\nDHT disconnected!\n");
118 }
119
120 doMessenger();
121}
122
123static void load_data() {
124 FILE* fd;
125 size_t len;
126 uint8_t* buf;
127
128 if((fd = fopen("data", "r")) != NULL) {
129 fseek(fd, 0, SEEK_END);
130 len = ftell(fd);
131 fseek(fd, 0, SEEK_SET);
132
133 buf = malloc(len);
134
135 if(buf == NULL) {
136 fprintf(stderr, "malloc() failed.\n");
137 fclose(fd);
138 exit(1);
139 }
140
141 if(fread(buf, len, 1, fd) != 1){
142 fprintf(stderr, "fread() failed.\n");
143 free(buf);
144 fclose(fd);
145 exit(1);
146 }
147
148 Messenger_load(buf, len);
149 }
150 else {
151 len = Messenger_size();
152 buf = malloc(len);
153
154 if(buf == NULL) {
155 fprintf(stderr, "malloc() failed.\n");
156 exit(1);
157 }
158
159 Messenger_save(buf);
160
161 fd = fopen("data", "w");
162 if(fd == NULL) {
163 fprintf(stderr, "fopen() failed.\n");
164 free(buf);
165 exit(1);
166 }
167
168 if(fwrite(buf, len, 1, fd) != 1){
169 fprintf(stderr, "fwrite() failed.\n");
170 free(buf);
171 fclose(fd);
172 exit(1);
173 }
174 }
175
176 free(buf);
177 fclose(fd);
178}
179
180static void draw_bar() {
181 size_t i;
182
183 attron(COLOR_PAIR(4));
184 mvhline(LINES - 2, 0, '_', COLS);
185 attroff(COLOR_PAIR(4));
186
187 move(LINES - 1, 0);
188
189 for(i=0; i<w_num; i++) {
190 if(i == w_active) {
191 attron(A_BOLD);
192 }
193
194 printw(" %s ", windows[i].title);
195
196 if(i == w_active) {
197 attroff(A_BOLD);
198 }
199 }
200
201 refresh();
202}
203
204int main(int argc, char* argv[]) {
205 int ch;
206 ToxWindow* a;
207
208 init_term();
209 init_tox();
210 load_data();
211 init_windows();
212
213 while(true) {
214 do_tox();
215
216 a = &windows[w_active];
217 a->onDraw(a);
218 draw_bar();
219
220 ch = getch();
221 if(ch != ERR) {
222 a->onKey(a, ch);
223 }
224
225 }
226
227 return 0;
228}
229
diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c
new file mode 100644
index 00000000..4a59cc7b
--- /dev/null
+++ b/testing/toxic/prompt.c
@@ -0,0 +1,292 @@
1/*
2 * Toxic -- Tox Curses Client
3 */
4
5#include <stdlib.h>
6#include <string.h>
7#include <ctype.h>
8#include <curses.h>
9
10#include "../../core/Messenger.h"
11#include "../../core/network.h"
12
13#include "windows.h"
14
15uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX
16uint8_t num_requests=0; // XXX
17
18// XXX:
19int add_req(uint8_t* public_key) {
20 memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE);
21 ++num_requests;
22
23 return num_requests-1;
24}
25
26// XXX: FIX
27unsigned char * hex_string_to_bin(char hex_string[])
28{
29 size_t len = strlen(hex_string);
30 unsigned char *val = malloc(len);
31 char *pos = hex_string;
32 int i;
33 for(i = 0; i < len; ++i, pos+=2)
34 sscanf(pos,"%2hhx",&val[i]);
35 return val;
36}
37
38static char prompt_buf[256] = {0};
39static int prompt_buf_pos=0;
40
41static void execute(ToxWindow* self, char* cmd) {
42
43 // quit/exit: Exit program.
44 if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit")) {
45 endwin();
46 exit(0);
47 }
48 else if(!strncmp(cmd, "connect ", strlen("connect "))) {
49 char* ip;
50 char* port;
51 char* key;
52 IP_Port dht;
53
54 ip = strchr(cmd, ' ');
55 if(ip == NULL) {
56 return;
57 }
58
59 ip++;
60
61 port = strchr(ip, ' ');
62 if(port == NULL) {
63 return;
64 }
65
66 port[0] = 0;
67 port++;
68
69 key = strchr(port, ' ');
70 if(key == NULL) {
71 return;
72 }
73
74 key[0] = 0;
75 key++;
76
77 if(atoi(port) == 0) {
78 return;
79 }
80
81 wprintw(self->window, "ip=%s, port=%s, key=%s\n", ip, port, key);
82
83 dht.port = htons(atoi(port));
84
85 int resolved_address = resolve_addr(ip);
86 if (resolved_address == -1) {
87 return;
88 }
89
90 dht.ip.i = resolved_address;
91 DHT_bootstrap(dht, hex_string_to_bin(key));
92 }
93 else if(!strncmp(cmd, "add ", strlen("add "))) {
94 char* id;
95 char* msg;
96 int num;
97
98 id = strchr(cmd, ' ');
99
100 if(id == NULL) {
101 return;
102 }
103
104 id++;
105
106 msg = strchr(id, ' ');
107 if(msg == NULL) {
108 return;
109 }
110
111 msg[0] = 0;
112 msg++;
113
114 num = m_addfriend((uint8_t*) id, (uint8_t*) msg, strlen(msg)+1);
115 wprintw(self->window, "Friend added as %d.\n", num);
116 }
117 else if(!strncmp(cmd, "status ", strlen("status "))) {
118 char* msg;
119
120 msg = strchr(cmd, ' ');
121 if(msg == NULL) {
122 return;
123 }
124
125 msg++;
126 m_set_userstatus((uint8_t*) msg, strlen(msg)+1);
127 wprintw(self->window, "Status set to: %s.\n", msg);
128 }
129 else if(!strncmp(cmd, "nick ", strlen("nick "))) {
130 char* nick;
131
132 nick = strchr(cmd, ' ');
133 if(nick == NULL) {
134 return;
135 }
136
137 nick++;
138 setname((uint8_t*) nick, strlen(nick)+1);
139 wprintw(self->window, "Nickname set to: %s.\n", nick);
140 }
141 else if(!strcmp(cmd, "myid")) {
142 // XXX: Clean this up
143 char idstring0[200];
144 char idstring1[32][5];
145 char idstring2[32][5];
146 uint32_t i;
147
148 for(i = 0; i < 32; i++) {
149 if(self_public_key[i] < 16)
150 strcpy(idstring1[i], "0");
151 else
152 strcpy(idstring1[i], "");
153
154 sprintf(idstring2[i], "%hhX", self_public_key[i]);
155 }
156
157 for (i=0; i<32; i++) {
158 strcat(idstring0, idstring1[i]);
159 strcat(idstring0, idstring2[i]);
160 }
161
162 wprintw(self->window, "%s\n", idstring0);
163 }
164 else if(!strncmp(cmd, "accept ", strlen("accept "))) {
165 char* id;
166 int num;
167
168 id = strchr(cmd, ' ');
169 if(id == NULL) {
170 return;
171 }
172 id++;
173
174 num = atoi(id);
175 if(num >= num_requests) {
176 return;
177 }
178
179 num = m_addfriend_norequest(pending_requests[num]);
180 wprintw(self->window, "Friend accepted as: %d.\n", num);
181 }
182 else if(!strncmp(cmd, "msg ", strlen("msg "))) {
183 char* id;
184 char* msg;
185
186 id = strchr(cmd, ' ');
187
188 if(id == NULL) {
189 return;
190 }
191
192 id++;
193
194 msg = strchr(id, ' ');
195 if(msg == NULL) {
196 return;
197 }
198
199 msg[0] = 0;
200 msg++;
201
202 if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) != 1) {
203 wprintw(self->window, "Error occurred while sending message.\n");
204 }
205 else {
206 wprintw(self->window, "Message successfully sent.\n");
207 }
208 }
209}
210
211static void prompt_onKey(ToxWindow* self, int key) {
212
213 // PRINTABLE characters: Add to line.
214 if(isprint(key)) {
215
216 if(prompt_buf_pos == (sizeof(prompt_buf) - 1)) {
217 return;
218 }
219
220 prompt_buf[prompt_buf_pos++] = key;
221 prompt_buf[prompt_buf_pos] = 0;
222 }
223
224 // RETURN key: execute command.
225 else if(key == '\n') {
226 wprintw(self->window, "\n");
227 execute(self, prompt_buf);
228
229 prompt_buf_pos = 0;
230 prompt_buf[0] = 0;
231 }
232
233 // BACKSPACE key: Remove one character from line.
234 else if(key == 0x107) {
235
236 if(prompt_buf_pos != 0) {
237 prompt_buf[--prompt_buf_pos] = 0;
238 }
239 }
240}
241
242static void prompt_onDraw(ToxWindow* self) {
243 int x, y;
244
245 mvwin(self->window,0,0);
246 wresize(self->window, LINES-2, COLS);
247
248 getyx(self->window, y, x);
249 (void) x;
250
251 wattron(self->window, COLOR_PAIR(1));
252 mvwprintw(self->window, y, 0, "# ");
253 wattroff(self->window, COLOR_PAIR(1));
254
255 mvwprintw(self->window, y, 2, "%s", prompt_buf);
256 wclrtoeol(self->window);
257
258 wrefresh(self->window);
259}
260
261static void print_usage(ToxWindow* self) {
262 wattron(self->window, COLOR_PAIR(2) | A_BOLD);
263 wprintw(self->window, "Usage:\n");
264 wattroff(self->window, A_BOLD);
265
266 wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n");
267 wprintw(self->window, " add <id> <message> : Add friend\n");
268 wprintw(self->window, " status <message> : Set your status\n");
269 wprintw(self->window, " nick <nickname> : Set your nickname\n");
270 wprintw(self->window, " accept <number> : Accept friend request\n");
271 wprintw(self->window, " myid : Print your ID\n");
272 wprintw(self->window, " quit/exit : Exit program\n");
273 wattroff(self->window, COLOR_PAIR(2));
274}
275
276static void prompt_onInit(ToxWindow* self) {
277 scrollok(self->window, 1);
278
279 print_usage(self);
280 wclrtoeol(self->window);
281}
282
283ToxWindow new_prompt() {
284 ToxWindow ret;
285
286 ret.onKey = &prompt_onKey;
287 ret.onDraw = &prompt_onDraw;
288 ret.onInit = &prompt_onInit;
289 strcpy(ret.title, "[prompt]");
290
291 return ret;
292}
diff --git a/testing/toxic/windows.h b/testing/toxic/windows.h
new file mode 100644
index 00000000..2e082ca9
--- /dev/null
+++ b/testing/toxic/windows.h
@@ -0,0 +1,10 @@
1typedef struct ToxWindow_ ToxWindow;
2
3struct ToxWindow_ {
4 void(*onKey)(ToxWindow*, int);
5 void(*onDraw)(ToxWindow*);
6 void(*onInit)(ToxWindow*);
7 char title[256];
8
9 WINDOW* window;
10};