1 /* Tox Shell
2  *
3  * Proof of concept ssh like server software using tox.
4  *
5  * Command line arguments are the ip, port and public_key of a node (for bootstrapping).
6  *
7  * EX: ./test 127.0.0.1 33445 CDCFD319CE3460824B33BE58FD86B8941C9585181D8FBD7C79C5721D7C2E9F7C
8  */
9 
10 /*
11  * Copyright © 2016-2017 The TokTok team.
12  * Copyright © 2014 Tox project.
13  *
14  * This file is part of Tox, the free peer to peer instant messenger.
15  *
16  * Tox is free software: you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation, either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * Tox is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with Tox.  If not, see <http://www.gnu.org/licenses/>.
28  */
29 #define _XOPEN_SOURCE 600
30 
31 #include <tox/tox.h>
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 
37 #include "../util/misc_tools.h"
38 
39 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
40 #include <util.h>
41 #elif defined(__FreeBSD__) || defined(__DragonFly__)
42 #include <libutil.h>
43 #else
44 #include <pty.h>
45 #endif
46 #include <fcntl.h>
47 
print_online(Tox * tox,uint32_t friendnumber,TOX_CONNECTION status,void * userdata)48 static void print_online(Tox *tox, uint32_t friendnumber, TOX_CONNECTION status, void *userdata)
49 {
50     if (status) {
51         printf("\nOther went online.\n");
52     } else {
53         printf("\nOther went offline.\n");
54     }
55 }
56 
print_message(Tox * tox,uint32_t friendnumber,TOX_MESSAGE_TYPE type,const uint8_t * string,size_t length,void * userdata)57 static void print_message(Tox *tox, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const uint8_t *string, size_t length,
58                           void *userdata)
59 {
60     int master = *((int *)userdata);
61     write(master, string, length);
62     write(master, "\n", 1);
63 }
64 
main(int argc,char * argv[])65 int main(int argc, char *argv[])
66 {
67     uint8_t ipv6enabled = 1; /* x */
68     int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
69 
70     if (argvoffset == -1) {
71         exit(1);
72     }
73 
74     /* with optional --ipvx, now it can be 1-4 arguments... */
75     if ((argc != argvoffset + 2) && (argc != argvoffset + 4)) {
76         printf("Usage: %s [--ipv4|--ipv6] ip port public_key (of the DHT bootstrap node)\n", argv[0]);
77         exit(0);
78     }
79 
80     int *master = (int *)malloc(sizeof(int));
81     int ret = forkpty(master, nullptr, nullptr, nullptr);
82 
83     if (ret == -1) {
84         printf("fork failed\n");
85         free(master);
86         return 1;
87     }
88 
89     if (ret == 0) {
90         execl("/bin/sh", "sh", nullptr);
91         return 0;
92     }
93 
94     int flags = fcntl(*master, F_GETFL, 0);
95     int r = fcntl(*master, F_SETFL, flags | O_NONBLOCK);
96 
97     if (r < 0) {
98         printf("error setting flags\n");
99     }
100 
101     Tox *tox = tox_new(0, 0);
102     tox_callback_friend_connection_status(tox, print_online);
103     tox_callback_friend_message(tox, print_message);
104 
105 
106     uint16_t port = atoi(argv[argvoffset + 2]);
107     unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
108     int res = tox_bootstrap(tox, argv[argvoffset + 1], port, binary_string, 0);
109     free(binary_string);
110 
111     if (!res) {
112         printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]);
113         exit(1);
114     }
115 
116     uint8_t address[TOX_ADDRESS_SIZE];
117     tox_self_get_address(tox, address);
118     uint32_t i;
119 
120     for (i = 0; i < TOX_ADDRESS_SIZE; i++) {
121         printf("%02X", address[i]);
122     }
123 
124     char temp_id[128];
125     printf("\nEnter the address of the other id you want to sync with (38 bytes HEX format):\n");
126 
127     if (scanf("%s", temp_id) != 1) {
128         return 1;
129     }
130 
131     uint8_t *bin_id = hex_string_to_bin(temp_id);
132     uint32_t num = tox_friend_add(tox, bin_id, (const uint8_t *)"Install Gentoo", sizeof("Install Gentoo"), 0);
133     free(bin_id);
134 
135     if (num == UINT32_MAX) {
136         printf("\nSomething went wrong when adding friend.\n");
137         return 1;
138     }
139 
140     uint8_t notconnected = 1;
141 
142     while (1) {
143         if (tox_self_get_connection_status(tox) && notconnected) {
144             printf("\nDHT connected.\n");
145             notconnected = 0;
146         }
147 
148         while (tox_friend_get_connection_status(tox, num, 0)) {
149             uint8_t buf[TOX_MAX_MESSAGE_LENGTH];
150             ret = read(*master, buf, sizeof(buf));
151 
152             if (ret <= 0) {
153                 break;
154             }
155 
156             tox_friend_send_message(tox, num, TOX_MESSAGE_TYPE_NORMAL, buf, ret, 0);
157         }
158 
159         tox_iterate(tox, master);
160         c_sleep(1);
161     }
162 }
163