toxcore/testing/Messenger_test.c

217 lines
6.5 KiB
C
Raw Normal View History

2013-07-10 01:27:47 +08:00
/* Messenger test
*
2013-07-10 01:27:47 +08:00
* This program adds a friend and accepts all friend requests with the proper message.
*
2013-07-10 01:27:47 +08:00
* It tries sending a message to the added friend.
*
* If it receives a message from a friend it replies back.
*
*
* This is how I compile it: gcc -O2 -Wall -D VANILLA_NACL -o test ../core/Lossless_UDP.c ../core/network.c ../core/net_crypto.c ../core/Messenger.c ../core/DHT.c ../nacl/build/${HOSTNAME%.*}/lib/amd64/{cpucycles.o,libnacl.a,randombytes.o} Messenger_test.c
2013-07-10 01:27:47 +08:00
*
*
* Command line arguments are the ip, port and public_key of a node (for bootstrapping).
*
* EX: ./test 127.0.0.1 33445 CDCFD319CE3460824B33BE58FD86B8941C9585181D8FBD7C79C5721D7C2E9F7C
*
* Or the argument can be the path to the save file.
*
* EX: ./test Save.bak
*/
/*
* Copyright © 2016-2017 The TokTok team.
* Copyright © 2013 Tox project.
*
* This file is part of Tox, the free peer to peer instant messenger.
*
* Tox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
2013-07-10 01:27:47 +08:00
*/
#define _XOPEN_SOURCE 600
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "../toxcore/Messenger.h"
#include "misc_tools.c"
2013-07-09 08:50:25 +08:00
2014-01-20 07:18:25 +08:00
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
2013-07-09 08:50:25 +08:00
#define c_sleep(x) Sleep(1*x)
#else
#include <arpa/inet.h>
2016-09-01 07:33:20 +08:00
#include <unistd.h>
2013-07-09 08:50:25 +08:00
#define c_sleep(x) usleep(1000*x)
2013-08-21 04:36:22 +08:00
#define PORT 33445
2013-07-09 08:50:25 +08:00
#endif
static void print_message(Messenger *m, uint32_t friendnumber, unsigned int type, const uint8_t *string, size_t length,
void *userdata)
2013-09-27 17:24:33 +08:00
{
printf("Message with length %zu received from %u: %s \n", length, friendnumber, string);
m_send_message_generic(m, friendnumber, type, (const uint8_t *)"Test1", 6, 0);
2013-09-27 17:24:33 +08:00
}
/* TODO(irungentoo): needed as print_request has to match the interface expected by
* networking_requesthandler and so cannot take a Messenger * */
static Messenger *m;
static void print_request(Messenger *m2, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
2013-07-09 08:50:25 +08:00
{
printf("Friend request received from: \n");
2013-07-09 08:50:25 +08:00
printf("ClientID: ");
uint32_t j;
2013-08-17 01:11:09 +08:00
for (j = 0; j < 32; j++) {
2016-09-01 02:12:19 +08:00
if (public_key[j] < 16) {
2013-07-09 08:50:25 +08:00
printf("0");
2016-09-01 02:12:19 +08:00
}
2013-08-17 01:11:09 +08:00
2013-07-09 08:50:25 +08:00
printf("%hhX", public_key[j]);
}
2013-08-17 01:11:09 +08:00
printf("\nOf length: %zu with data: %s \n", length, data);
2013-08-17 01:11:09 +08:00
if (length != sizeof("Install Gentoo")) {
return;
}
2013-08-17 01:11:09 +08:00
if (memcmp(data , "Install Gentoo", sizeof("Install Gentoo")) == 0)
2013-08-17 01:11:09 +08:00
//if the request contained the message of peace the person is obviously a friend so we add him.
{
printf("Friend request accepted.\n");
m_addfriend_norequest(m2, public_key);
}
2013-07-09 08:50:25 +08:00
}
int main(int argc, char *argv[])
{
/* let user override default by cmdline */
uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
2013-09-15 00:42:17 +08:00
2016-09-01 02:12:19 +08:00
if (argvoffset < 0) {
exit(1);
2016-09-01 02:12:19 +08:00
}
/* with optional --ipvx, now it can be 1-4 arguments... */
if ((argc != argvoffset + 2) && (argc != argvoffset + 4)) {
printf("Usage: %s [--ipv4|--ipv6] ip port public_key (of the DHT bootstrap node)\n", argv[0]);
printf("or\n");
printf(" %s [--ipv4|--ipv6] Save.bak (to read Save.bak as state file)\n", argv[0]);
2013-07-09 08:50:25 +08:00
exit(0);
}
Messenger_Options options = {0};
options.ipv6enabled = ipv6enabled;
m = new_messenger(&options, 0);
2013-08-17 01:11:09 +08:00
if (!m) {
fputs("Failed to allocate messenger datastructure\n", stderr);
exit(0);
}
if (argc == argvoffset + 4) {
uint16_t port = net_htons(atoi(argv[argvoffset + 2]));
uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]);
int res = DHT_bootstrap_from_address(m->dht, argv[argvoffset + 1],
2013-09-15 00:42:17 +08:00
ipv6enabled, port, bootstrap_key);
free(bootstrap_key);
2013-09-15 00:42:17 +08:00
if (!res) {
printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]);
exit(1);
}
} else {
FILE *file = fopen(argv[argvoffset + 1], "rb");
2013-09-15 00:42:17 +08:00
if (file == NULL) {
printf("Failed to open \"%s\" - does it exist?\n", argv[argvoffset + 1]);
2013-08-17 01:11:09 +08:00
return 1;
}
int read;
uint8_t buffer[128000];
read = fread(buffer, 1, 128000, file);
2013-10-24 02:49:59 +08:00
printf("Messenger loaded: %i\n", messenger_load(m, buffer, read));
fclose(file);
}
2013-08-17 01:11:09 +08:00
m_callback_friendrequest(m, print_request);
m_callback_friendmessage(m, print_message);
2013-07-09 08:50:25 +08:00
printf("OUR ID: ");
uint32_t i;
2013-08-13 23:50:33 +08:00
uint8_t address[FRIEND_ADDRESS_SIZE];
getaddress(m, address);
2013-08-17 01:11:09 +08:00
for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) {
2016-09-01 02:12:19 +08:00
if (address[i] < 16) {
2013-07-09 08:50:25 +08:00
printf("0");
2016-09-01 02:12:19 +08:00
}
2013-08-17 01:11:09 +08:00
printf("%hhX", address[i]);
2013-07-09 08:50:25 +08:00
}
setname(m, (const uint8_t *)"Anon", 5);
char temp_hex_id[128];
2013-08-13 23:50:33 +08:00
printf("\nEnter the address of the friend you wish to add (38 bytes HEX format):\n");
2013-08-17 01:11:09 +08:00
2016-09-01 02:12:19 +08:00
if (!fgets(temp_hex_id, sizeof(temp_hex_id), stdin)) {
2014-02-26 00:48:27 +08:00
exit(0);
2016-09-01 02:12:19 +08:00
}
2014-02-26 00:48:27 +08:00
2016-09-01 02:12:19 +08:00
if ((strlen(temp_hex_id) > 0) && (temp_hex_id[strlen(temp_hex_id) - 1] == '\n')) {
2014-02-26 00:48:27 +08:00
temp_hex_id[strlen(temp_hex_id) - 1] = '\0';
2016-09-01 02:12:19 +08:00
}
uint8_t *bin_id = hex_string_to_bin(temp_hex_id);
int num = m_addfriend(m, bin_id, (const uint8_t *)"Install Gentoo", sizeof("Install Gentoo"));
free(bin_id);
2013-07-09 08:50:25 +08:00
perror("Initialization");
2013-08-17 01:11:09 +08:00
while (1) {
2013-07-18 23:47:27 +08:00
uint8_t name[128];
getname(m, num, name);
2013-07-18 23:47:27 +08:00
printf("%s\n", name);
m_send_message_generic(m, num, MESSAGE_NORMAL, (const uint8_t *)"Test", 5, 0);
Make self_connection_status callback stateless. **What are we doing?** We are moving towards stateless callbacks. This means that when registering a callback, you no longer pass a user data pointer. Instead, you pass a user data pointer to tox_iterate. This pointer is threaded through the code, passed to each callback. The callback can modify the data pointed at. An extra indirection will be needed if the pointer itself can change. **Why?** Currently, callbacks are registered with a user data pointer. This means the library has N pointers for N different callbacks. These pointers need to be managed by the client code. Managing the lifetime of the pointee can be difficult. In C++, it takes special effort to ensure that the lifetime of user data extends at least beyond the lifetime of the Tox instance. For other languages, the situation is much worse. Java and other garbage collected languages may move objects in memory, so the pointers are not stable. Tox4j goes through a lot of effort to make the Java/Scala user experience a pleasant one by keeping a global array of Tox+userdata on the C++ side, and communicating via protobufs. A Haskell FFI would have to do similarly complex tricks. Stateless callbacks ensure that a user data pointer only needs to live during a single function call. This means that the user code (or language runtime) can move the data around at will, as long as it sets the new location in the callback. **How?** We are doing this change one callback at a time. After each callback, we ensure that everything still works as expected. This means the toxcore change will require 15 Pull Requests.
2016-08-10 20:46:04 +08:00
do_messenger(m, NULL);
c_sleep(30);
FILE *file = fopen("Save.bak", "wb");
2013-08-17 01:11:09 +08:00
if (file == NULL) {
2013-08-17 01:11:09 +08:00
return 1;
}
uint8_t *buffer = (uint8_t *)malloc(messenger_size(m));
2013-10-24 02:49:59 +08:00
messenger_save(m, buffer);
size_t write_result = fwrite(buffer, 1, messenger_size(m), file);
2013-08-17 01:11:09 +08:00
2013-10-24 02:49:59 +08:00
if (write_result < messenger_size(m)) {
2013-08-17 01:11:09 +08:00
return 1;
}
free(buffer);
fclose(file);
}
2013-08-17 01:11:09 +08:00
2013-10-24 02:49:59 +08:00
kill_messenger(m);
2013-07-09 08:50:25 +08:00
}