Merge remote-tracking branch 'ProjectTox/master'

This commit is contained in:
Astonex 2013-07-27 02:52:24 +01:00
commit 3e1b96f333
31 changed files with 1822 additions and 1500 deletions

View File

@ -4,6 +4,7 @@ compiler:
- clang - clang
before_script: before_script:
# installing libsodium, needed for Core
- git clone git://github.com/jedisct1/libsodium.git - git clone git://github.com/jedisct1/libsodium.git
- cd libsodium - cd libsodium
- git checkout tags/0.4.2 - git checkout tags/0.4.2
@ -12,6 +13,10 @@ before_script:
- sudo make install - sudo make install
- sudo ldconfig - sudo ldconfig
- cd .. - cd ..
# installing libconfig, needed for DHT_bootstrap_daemon
- sudo sed -i 's/precise/quantal/' /etc/apt/sources.list # needed for libconfig-dev
- sudo apt-get update -qq
- yes | sudo apt-get install libconfig-dev
script: script:
- mkdir build && cd build - mkdir build && cd build

View File

@ -56,6 +56,8 @@ You should install:
- [MinGW](http://sourceforge.net/projects/mingw/)'s C compiler - [MinGW](http://sourceforge.net/projects/mingw/)'s C compiler
- [CMake](http://www.cmake.org/cmake/resources/software.html) - [CMake](http://www.cmake.org/cmake/resources/software.html)
You have to [modify your PATH environment variable](http://www.computerhope.com/issues/ch000549.htm) so that it contains MinGW's bin folder path. With default settings, the bin folder is located at `C:\MinGW\bin`, which means that you would have to append `;C:\MinGW\bin` to the PATH variable.
Then you should either clone this repo by using git, or just download a [zip of current Master branch](https://github.com/irungentoo/ProjectTox-Core/archive/master.zip) and extract it somewhere. Then you should either clone this repo by using git, or just download a [zip of current Master branch](https://github.com/irungentoo/ProjectTox-Core/archive/master.zip) and extract it somewhere.
After that you should get precompiled packages of libsodium from [here](https://download.libsodium.org/libsodium/releases/) and extract the archive into this repo's root. That is, `sodium` folder should be along with `core`, `testing` and other folders. After that you should get precompiled packages of libsodium from [here](https://download.libsodium.org/libsodium/releases/) and extract the archive into this repo's root. That is, `sodium` folder should be along with `core`, `testing` and other folders.

View File

@ -11,6 +11,7 @@ set(core_sources
Lossless_UDP.c Lossless_UDP.c
net_crypto.c net_crypto.c
friend_requests.c friend_requests.c
LAN_discovery.c
Messenger.c) Messenger.c)
add_library(core ${core_sources}) add_library(core ${core_sources})

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +1,25 @@
/* DHT.h /* DHT.h
* *
* An implementation of the DHT as seen in docs/DHT.txt * An implementation of the DHT as seen in docs/DHT.txt
* *
* Copyright (C) 2013 Tox project All Rights Reserved.
Copyright (C) 2013 Tox project All Rights Reserved. *
* This file is part of Tox.
This file is part of Tox. *
* Tox is free software: you can redistribute it and/or modify
Tox is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or
the Free Software Foundation, either version 3 of the License, or * (at your option) any later version.
(at your option) any later version. *
* Tox is distributed in the hope that it will be useful,
Tox is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.
GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License * along with Tox. If not, see <http://www.gnu.org/licenses/>.
along with Tox. If not, see <http://www.gnu.org/licenses/>. *
*/
*/
#ifndef DHT_H #ifndef DHT_H
#define DHT_H #define DHT_H
@ -38,8 +36,6 @@ extern "C" {
/* size of the client_id in bytes */ /* size of the client_id in bytes */
#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES #define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES
/* Add a new friend to the friends list /* Add a new friend to the friends list
client_id must be CLIENT_ID_SIZE bytes long. client_id must be CLIENT_ID_SIZE bytes long.
returns 0 if success returns 0 if success
@ -52,7 +48,6 @@ int DHT_addfriend(uint8_t * client_id);
returns 1 if failure (client_id not in friends list) */ returns 1 if failure (client_id not in friends list) */
int DHT_delfriend(uint8_t * client_id); int DHT_delfriend(uint8_t * client_id);
/* Get ip of friend /* Get ip of friend
client_id must be CLIENT_ID_SIZE bytes long. client_id must be CLIENT_ID_SIZE bytes long.
ip must be 4 bytes long. ip must be 4 bytes long.
@ -62,7 +57,6 @@ int DHT_delfriend(uint8_t * client_id);
returns ip of 1 if friend is not in list. */ returns ip of 1 if friend is not in list. */
IP_Port DHT_getfriendip(uint8_t * client_id); IP_Port DHT_getfriendip(uint8_t * client_id);
/* Run this function at least a couple times per second (It's the main loop) */ /* Run this function at least a couple times per second (It's the main loop) */
void doDHT(); void doDHT();
@ -75,8 +69,6 @@ int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source);
Sends a get nodes request to the given node with ip port and public_key */ Sends a get nodes request to the given node with ip port and public_key */
void DHT_bootstrap(IP_Port ip_port, uint8_t * public_key); void DHT_bootstrap(IP_Port ip_port, uint8_t * public_key);
/* ROUTING FUNCTIONS */ /* ROUTING FUNCTIONS */
/* send the given packet to node with client_id /* send the given packet to node with client_id
@ -87,8 +79,6 @@ int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length);
returns the number of nodes it sent the packet to */ returns the number of nodes it sent the packet to */
int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length); int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length);
/* NAT PUNCHING FUNCTIONS */ /* NAT PUNCHING FUNCTIONS */
/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist /* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist
@ -97,8 +87,6 @@ int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length);
returns -1 if no such friend*/ returns -1 if no such friend*/
int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id); int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id);
/* SAVE/LOAD functions */ /* SAVE/LOAD functions */
/* get the size of the DHT (for saving) */ /* get the size of the DHT (for saving) */

79
core/LAN_discovery.c Normal file
View File

@ -0,0 +1,79 @@
/* LAN_discovery.c
*
* LAN discovery implementation.
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/
#include "LAN_discovery.h"
/*Return the broadcast ip
TODO: make it return the real one, not the 255.255.255.255 one.*/
IP broadcast_ip()
{
IP ip;
ip.i = ~0;
return ip;
}
/*return 0 if ip is a LAN ip
return -1 if it is not */
int LAN_ip(IP ip)
{
if(ip.c[0] == 127)/* Loopback */
return 0;
if(ip.c[0] == 10)/* 10.0.0.0 to 10.255.255.255 range */
return 0;
if(ip.c[0] == 172 && ip.c[1] >= 16 && ip.c[1] <= 31)/* 172.16.0.0 to 172.31.255.255 range */
return 0;
if(ip.c[0] == 192 && ip.c[1] == 168) /* 192.168.0.0 to 192.168.255.255 range */
return 0;
if(ip.c[0] == 169 && ip.c[1] == 254 && ip.c[2] != 0 && ip.c[2] != 255)/* 169.254.1.0 to 169.254.254.255 range */
return 0;
return -1;
}
int handle_LANdiscovery(uint8_t * packet, uint32_t length, IP_Port source)
{
if(LAN_ip(source.ip) == -1)
return 1;
if(length != crypto_box_PUBLICKEYBYTES + 1)
return 1;
DHT_bootstrap(source, packet + 1);
return 0;
}
int send_LANdiscovery(uint16_t port)
{
uint8_t data[crypto_box_PUBLICKEYBYTES + 1];
data[0] = 32;
memcpy(data + 1, self_public_key, crypto_box_PUBLICKEYBYTES);
IP_Port ip_port = {broadcast_ip(), port};
return sendpacket(ip_port, data, 1 + crypto_box_PUBLICKEYBYTES);
}
int LANdiscovery_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
{
if(packet[0] == 32)
return handle_LANdiscovery(packet, length, source);
return 1;
}

50
core/LAN_discovery.h Normal file
View File

@ -0,0 +1,50 @@
/* LAN_discovery.h
*
* LAN discovery implementation.
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/
#ifndef LAN_DISCOVERY_H
#define LAN_DISCOVERY_H
#include "DHT.h"
#ifdef __cplusplus
extern "C" {
#endif
/*Send a LAN discovery pcaket to the broadcast address with port port*/
int send_LANdiscovery(uint16_t port);
/* if we receive a packet we call this function so it can be handled.
return 0 if packet is handled correctly.
return 1 if it didn't handle the packet or if the packet was shit. */
int LANdiscovery_handlepacket(uint8_t * packet, uint32_t length, IP_Port source);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,32 +1,30 @@
/* Lossless_UDP.c /* Lossless_UDP.c
* *
* An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt * An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt
* *
* Copyright (C) 2013 Tox project All Rights Reserved.
Copyright (C) 2013 Tox project All Rights Reserved. *
* This file is part of Tox.
*
* 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/>.
*
*/
This file is part of Tox.
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/>.
*/
/* TODO: clean this file a bit. /* TODO: clean this file a bit.
There are a couple of useless variables to get rid of. */ There are a couple of useless variables to get rid of. */
#include "Lossless_UDP.h" #include "Lossless_UDP.h"
/* maximum data packets in sent and receive queues. */ /* maximum data packets in sent and receive queues. */
#define MAX_QUEUE_NUM 16 #define MAX_QUEUE_NUM 16
@ -88,7 +86,6 @@ typedef struct
uint8_t timeout; /* connection timeout in seconds. */ uint8_t timeout; /* connection timeout in seconds. */
}Connection; }Connection;
#define MAX_CONNECTIONS 256 #define MAX_CONNECTIONS 256
static Connection connections[MAX_CONNECTIONS]; static Connection connections[MAX_CONNECTIONS];
@ -104,40 +101,31 @@ int getconnection_id(IP_Port ip_port)
{ {
uint32_t i; uint32_t i;
for(i = 0; i < MAX_CONNECTIONS; ++i) for(i = 0; i < MAX_CONNECTIONS; ++i)
{
if(connections[i].ip_port.ip.i == ip_port.ip.i && if(connections[i].ip_port.ip.i == ip_port.ip.i &&
connections[i].ip_port.port == ip_port.port && connections[i].status > 0) connections[i].ip_port.port == ip_port.port && connections[i].status > 0)
{
return i; return i;
}
}
return -1; return -1;
} }
/* table of random numbers used below. */ /* table of random numbers used below. */
static uint32_t randtable[6][256]; static uint32_t randtable[6][256];
/* generate a handshake_id which depends on the ip_port. /* generate a handshake_id which depends on the ip_port.
this function will always give one unique handshake_id per ip_port. this function will always give one unique handshake_id per ip_port.
TODO: make this better */ TODO: make this better */
uint32_t handshake_id(IP_Port source) uint32_t handshake_id(IP_Port source)
{ {
uint32_t id = 0, i; uint32_t id = 0, i;
for(i = 0; i < 6; ++i) for(i = 0; i < 6; ++i) {
{
if(randtable[i][((uint8_t *)&source)[i]] == 0) if(randtable[i][((uint8_t *)&source)[i]] == 0)
{
randtable[i][((uint8_t *)&source)[i]] = random_int(); randtable[i][((uint8_t *)&source)[i]] = random_int();
}
id ^= randtable[i][((uint8_t *)&source)[i]]; id ^= randtable[i][((uint8_t *)&source)[i]];
} }
if(id == 0) /* id can't be zero */ if(id == 0) /* id can't be zero */
{
id = 1; id = 1;
}
return id; return id;
} }
/* change the hnshake id associated with that ip_port /* change the hnshake id associated with that ip_port
TODO: make this better */ TODO: make this better */
void change_handshake(IP_Port source) void change_handshake(IP_Port source)
@ -146,7 +134,6 @@ void change_handshake(IP_Port source)
randtable[rand][((uint8_t *)&source)[rand]] = random_int(); randtable[rand][((uint8_t *)&source)[rand]] = random_int();
} }
/* initialize a new connection to ip_port /* initialize a new connection to ip_port
returns an integer corresponding to the connection id. returns an integer corresponding to the connection id.
return -1 if it could not initialize the connection. return -1 if it could not initialize the connection.
@ -155,14 +142,10 @@ int new_connection(IP_Port ip_port)
{ {
int connect = getconnection_id(ip_port); int connect = getconnection_id(ip_port);
if(connect != -1) if(connect != -1)
{
return connect; return connect;
}
uint32_t i; uint32_t i;
for(i = 0; i < MAX_CONNECTIONS; ++i) for(i = 0; i < MAX_CONNECTIONS; ++i) {
{ if(connections[i].status == 0) {
if(connections[i].status == 0)
{
memset(&connections[i], 0, sizeof(Connection)); memset(&connections[i], 0, sizeof(Connection));
connections[i].ip_port = ip_port; connections[i].ip_port = ip_port;
connections[i].status = 1; connections[i].status = 1;
@ -191,14 +174,10 @@ int new_connection(IP_Port ip_port)
int new_inconnection(IP_Port ip_port) int new_inconnection(IP_Port ip_port)
{ {
if(getconnection_id(ip_port) != -1) if(getconnection_id(ip_port) != -1)
{
return -1; return -1;
}
uint32_t i; uint32_t i;
for(i = 0; i < MAX_CONNECTIONS; ++i) for(i = 0; i < MAX_CONNECTIONS; ++i) {
{ if(connections[i].status == 0) {
if(connections[i].status == 0)
{
memset(&connections[i], 0, sizeof(Connection)); memset(&connections[i], 0, sizeof(Connection));
connections[i].ip_port = ip_port; connections[i].ip_port = ip_port;
connections[i].status = 2; connections[i].status = 2;
@ -224,13 +203,10 @@ int incoming_connection()
{ {
uint32_t i; uint32_t i;
for(i = 0; i < MAX_CONNECTIONS; ++i) for(i = 0; i < MAX_CONNECTIONS; ++i)
{ if(connections[i].inbound == 2) {
if(connections[i].inbound == 2)
{
connections[i].inbound = 1; connections[i].inbound = 1;
return i; return i;
} }
}
return -1; return -1;
} }
@ -239,14 +215,11 @@ int incoming_connection()
int kill_connection(int connection_id) int kill_connection(int connection_id)
{ {
if(connection_id >= 0 && connection_id < MAX_CONNECTIONS) if(connection_id >= 0 && connection_id < MAX_CONNECTIONS)
{ if(connections[connection_id].status > 0) {
if(connections[connection_id].status > 0)
{
connections[connection_id].status = 0; connections[connection_id].status = 0;
change_handshake(connections[connection_id].ip_port); change_handshake(connections[connection_id].ip_port);
return 0; return 0;
} }
}
return -1; return -1;
} }
@ -256,13 +229,10 @@ int kill_connection(int connection_id)
int kill_connection_in(int connection_id, uint32_t seconds) int kill_connection_in(int connection_id, uint32_t seconds)
{ {
if(connection_id >= 0 && connection_id < MAX_CONNECTIONS) if(connection_id >= 0 && connection_id < MAX_CONNECTIONS)
{ if(connections[connection_id].status > 0) {
if(connections[connection_id].status > 0)
{
connections[connection_id].killat = current_time() + 1000000UL*seconds; connections[connection_id].killat = current_time() + 1000000UL*seconds;
return 0; return 0;
} }
}
return -1; return -1;
} }
@ -275,9 +245,7 @@ int kill_connection_in(int connection_id, uint32_t seconds)
int is_connected(int connection_id) int is_connected(int connection_id)
{ {
if(connection_id >= 0 && connection_id < MAX_CONNECTIONS) if(connection_id >= 0 && connection_id < MAX_CONNECTIONS)
{
return connections[connection_id].status; return connections[connection_id].status;
}
return 0; return 0;
} }
@ -285,9 +253,7 @@ int is_connected(int connection_id)
IP_Port connection_ip(int connection_id) IP_Port connection_ip(int connection_id)
{ {
if(connection_id >= 0 && connection_id < MAX_CONNECTIONS) if(connection_id >= 0 && connection_id < MAX_CONNECTIONS)
{
return connections[connection_id].ip_port; return connections[connection_id].ip_port;
}
IP_Port zero = {{{0}}, 0}; IP_Port zero = {{{0}}, 0};
return zero; return zero;
} }
@ -309,17 +275,15 @@ uint32_t recvqueue(int connection_id)
char id_packet(int connection_id) char id_packet(int connection_id)
{ {
if(recvqueue(connection_id) != 0 && connections[connection_id].status != 0) if(recvqueue(connection_id) != 0 && connections[connection_id].status != 0)
{
return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0]; return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0];
}
return -1; return -1;
} }
/* return 0 if there is no received data in the buffer. /* return 0 if there is no received data in the buffer.
return length of received packet if successful */ return length of received packet if successful */
int read_packet(int connection_id, uint8_t * data) int read_packet(int connection_id, uint8_t * data)
{ {
if(recvqueue(connection_id) != 0) if(recvqueue(connection_id) != 0) {
{
uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM; uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM;
uint16_t size = connections[connection_id].recvbuffer[index].size; uint16_t size = connections[connection_id].recvbuffer[index].size;
memcpy(data, connections[connection_id].recvbuffer[index].data, size); memcpy(data, connections[connection_id].recvbuffer[index].data, size);
@ -335,15 +299,10 @@ int read_packet(int connection_id, uint8_t * data)
int write_packet(int connection_id, uint8_t * data, uint32_t length) int write_packet(int connection_id, uint8_t * data, uint32_t length)
{ {
if(length > MAX_DATA_SIZE) if(length > MAX_DATA_SIZE)
{
return 0; return 0;
}
if(length == 0) if(length == 0)
{
return 0; return 0;
} if(sendqueue(connection_id) < BUFFER_PACKET_NUM) {
if(sendqueue(connection_id) < BUFFER_PACKET_NUM)
{
uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM; uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM;
memcpy(connections[connection_id].sendbuffer[index].data, data, length); memcpy(connections[connection_id].sendbuffer[index].data, data, length);
connections[connection_id].sendbuffer[index].size = length; connections[connection_id].sendbuffer[index].size = length;
@ -353,9 +312,6 @@ int write_packet(int connection_id, uint8_t * data, uint32_t length)
return 0; return 0;
} }
/* put the packet numbers the we are missing in requested and return the number */ /* put the packet numbers the we are missing in requested and return the number */
uint32_t missing_packets(int connection_id, uint32_t * requested) uint32_t missing_packets(int connection_id, uint32_t * requested)
{ {
@ -363,59 +319,47 @@ uint32_t missing_packets(int connection_id, uint32_t * requested)
uint32_t i; uint32_t i;
uint32_t temp; uint32_t temp;
if(recvqueue(connection_id) >= (BUFFER_PACKET_NUM - 1)) /* don't request packets if the buffer is full. */ if(recvqueue(connection_id) >= (BUFFER_PACKET_NUM - 1)) /* don't request packets if the buffer is full. */
{
return 0; return 0;
}
for(i = connections[connection_id].recv_packetnum; i != connections[connection_id].osent_packetnum; i++ ) for(i = connections[connection_id].recv_packetnum; i != connections[connection_id].osent_packetnum; i++ )
{ if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) {
if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0)
{
temp = htonl(i); temp = htonl(i);
memcpy(requested + number, &temp, 4); memcpy(requested + number, &temp, 4);
++number; ++number;
} }
}
if(number == 0) if(number == 0)
{
connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum; connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum;
}
return number; return number;
} }
/* Packet sending functions /* Packet sending functions
One per packet type. One per packet type.
see docs/Lossless_UDP.txt for more information. */ see docs/Lossless_UDP.txt for more information. */
int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2)
{ {
uint8_t packet[1 + 4 + 4]; uint8_t packet[1 + 4 + 4];
uint32_t temp; uint32_t temp;
packet[0] = 16; packet[0] = 16;
temp = htonl(handshake_id1); temp = htonl(handshake_id1);
memcpy(packet + 1, &temp, 4); memcpy(packet + 1, &temp, 4);
temp = htonl(handshake_id2); temp = htonl(handshake_id2);
memcpy(packet + 5, &temp, 4); memcpy(packet + 5, &temp, 4);
return sendpacket(ip_port, packet, sizeof(packet)); return sendpacket(ip_port, packet, sizeof(packet));
} }
int send_SYNC(uint32_t connection_id) int send_SYNC(uint32_t connection_id)
{ {
uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)]; uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)];
uint16_t index = 0; uint16_t index = 0;
IP_Port ip_port = connections[connection_id].ip_port; IP_Port ip_port = connections[connection_id].ip_port;
uint8_t counter = connections[connection_id].send_counter; uint8_t counter = connections[connection_id].send_counter;
uint32_t recv_packetnum = htonl(connections[connection_id].recv_packetnum); uint32_t recv_packetnum = htonl(connections[connection_id].recv_packetnum);
uint32_t sent_packetnum = htonl(connections[connection_id].sent_packetnum); uint32_t sent_packetnum = htonl(connections[connection_id].sent_packetnum);
uint32_t requested[BUFFER_PACKET_NUM]; uint32_t requested[BUFFER_PACKET_NUM];
uint32_t number = missing_packets(connection_id, requested); uint32_t number = missing_packets(connection_id, requested);
packet[0] = 17; packet[0] = 17;
index += 1; index += 1;
memcpy(packet + index, &counter, 1); memcpy(packet + index, &counter, 1);
@ -427,7 +371,7 @@ int send_SYNC(uint32_t connection_id)
memcpy(packet + index, requested, 4 * number); memcpy(packet + index, requested, 4 * number);
return sendpacket(ip_port, packet, (number*4 + 4 + 4 + 2)); return sendpacket(ip_port, packet, (number*4 + 4 + 4 + 2));
} }
int send_data_packet(uint32_t connection_id, uint32_t packet_num) int send_data_packet(uint32_t connection_id, uint32_t packet_num)
@ -449,16 +393,14 @@ int send_DATA(uint32_t connection_id)
{ {
int ret; int ret;
uint32_t buffer[BUFFER_PACKET_NUM]; uint32_t buffer[BUFFER_PACKET_NUM];
if(connections[connection_id].num_req_paquets > 0) if(connections[connection_id].num_req_paquets > 0) {
{
ret = send_data_packet(connection_id, connections[connection_id].req_packets[0]); ret = send_data_packet(connection_id, connections[connection_id].req_packets[0]);
connections[connection_id].num_req_paquets--; connections[connection_id].num_req_paquets--;
memcpy(buffer, connections[connection_id].req_packets + 1, connections[connection_id].num_req_paquets * 4); memcpy(buffer, connections[connection_id].req_packets + 1, connections[connection_id].num_req_paquets * 4);
memcpy(connections[connection_id].req_packets, buffer, connections[connection_id].num_req_paquets * 4); memcpy(connections[connection_id].req_packets, buffer, connections[connection_id].num_req_paquets * 4);
return ret; return ret;
} }
if(connections[connection_id].sendbuff_packetnum != connections[connection_id].sent_packetnum) if(connections[connection_id].sendbuff_packetnum != connections[connection_id].sent_packetnum) {
{
ret = send_data_packet(connection_id, connections[connection_id].sent_packetnum); ret = send_data_packet(connection_id, connections[connection_id].sent_packetnum);
connections[connection_id].sent_packetnum++; connections[connection_id].sent_packetnum++;
return ret; return ret;
@ -468,17 +410,13 @@ int send_DATA(uint32_t connection_id)
/* END of packet sending functions */ /* END of packet sending functions */
/* Packet handling functions /* Packet handling functions
One to handle each type of packets we receive One to handle each type of packets we receive
return 0 if handled correctly, 1 if packet is bad. */ return 0 if handled correctly, 1 if packet is bad. */
int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source) int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
{ {
if(length != (1 + 4 + 4)) if(length != (1 + 4 + 4))
{
return 1; return 1;
}
uint32_t temp; uint32_t temp;
uint32_t handshake_id1, handshake_id2; uint32_t handshake_id1, handshake_id2;
int connection = getconnection_id(source); int connection = getconnection_id(source);
@ -487,17 +425,13 @@ int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
memcpy(&temp, packet + 5, 4); memcpy(&temp, packet + 5, 4);
handshake_id2 = ntohl(temp); handshake_id2 = ntohl(temp);
if(handshake_id2 == 0) if(handshake_id2 == 0) {
{
send_handshake(source, handshake_id(source), handshake_id1); send_handshake(source, handshake_id(source), handshake_id1);
return 0; return 0;
} }
if(is_connected(connection) != 1) if(is_connected(connection) != 1)
{
return 1; return 1;
} if(handshake_id2 == connections[connection].handshake_id1) { /* if handshake_id2 is what we sent previously as handshake_id1 */
if(handshake_id2 == connections[connection].handshake_id1) /* if handshake_id2 is what we sent previously as handshake_id1 */
{
connections[connection].status = 2; connections[connection].status = 2;
/* NOTE: is this necessary? /* NOTE: is this necessary?
connections[connection].handshake_id2 = handshake_id1; */ connections[connection].handshake_id2 = handshake_id1; */
@ -515,25 +449,19 @@ int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
int SYNC_valid(uint32_t length) int SYNC_valid(uint32_t length)
{ {
if(length < 4 + 4 + 2) if(length < 4 + 4 + 2)
{
return 0; return 0;
}
if(length > (BUFFER_PACKET_NUM*4 + 4 + 4 + 2) || if(length > (BUFFER_PACKET_NUM*4 + 4 + 4 + 2) ||
((length - 4 - 4 - 2) % 4) != 0) ((length - 4 - 4 - 2) % 4) != 0)
{
return 0; return 0;
}
return 1; return 1;
} }
/* case 1: */ /* case 1: */
int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum)
{ {
if(handshake_id(source) == recv_packetnum) if(handshake_id(source) == recv_packetnum) {
{
int x = new_inconnection(source); int x = new_inconnection(source);
if(x != -1) if(x != -1) {
{
connections[x].orecv_packetnum = recv_packetnum; connections[x].orecv_packetnum = recv_packetnum;
connections[x].sent_packetnum = recv_packetnum; connections[x].sent_packetnum = recv_packetnum;
connections[x].sendbuff_packetnum = recv_packetnum; connections[x].sendbuff_packetnum = recv_packetnum;
@ -551,9 +479,8 @@ int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnu
/* case 2: */ /* case 2: */
int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum)
{ {
if(recv_packetnum == connections[connection_id].orecv_packetnum) if(recv_packetnum == connections[connection_id].orecv_packetnum) {
/* && sent_packetnum == connections[connection_id].osent_packetnum) */ /* && sent_packetnum == connections[connection_id].osent_packetnum) */
{
connections[connection_id].status = 3; connections[connection_id].status = 3;
connections[connection_id].recv_counter = counter; connections[connection_id].recv_counter = counter;
++connections[connection_id].send_counter; ++connections[connection_id].send_counter;
@ -572,16 +499,14 @@ int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, ui
uint32_t comp_2 = (sent_packetnum - connections[connection_id].successful_read); */ uint32_t comp_2 = (sent_packetnum - connections[connection_id].successful_read); */
uint32_t comp_1 = (recv_packetnum - connections[connection_id].orecv_packetnum); uint32_t comp_1 = (recv_packetnum - connections[connection_id].orecv_packetnum);
uint32_t comp_2 = (sent_packetnum - connections[connection_id].osent_packetnum); uint32_t comp_2 = (sent_packetnum - connections[connection_id].osent_packetnum);
if(comp_1 <= BUFFER_PACKET_NUM && comp_2 <= BUFFER_PACKET_NUM && comp_counter < 10 && comp_counter != 0) /* packet valid */ if(comp_1 <= BUFFER_PACKET_NUM && comp_2 <= BUFFER_PACKET_NUM && comp_counter < 10 && comp_counter != 0) { /* packet valid */
{
connections[connection_id].orecv_packetnum = recv_packetnum; connections[connection_id].orecv_packetnum = recv_packetnum;
connections[connection_id].osent_packetnum = sent_packetnum; connections[connection_id].osent_packetnum = sent_packetnum;
connections[connection_id].successful_sent = recv_packetnum; connections[connection_id].successful_sent = recv_packetnum;
connections[connection_id].last_recvSYNC = current_time(); connections[connection_id].last_recvSYNC = current_time();
connections[connection_id].recv_counter = counter; connections[connection_id].recv_counter = counter;
++connections[connection_id].send_counter; ++connections[connection_id].send_counter;
for(i = 0; i < number; ++i) for(i = 0; i < number; ++i) {
{
temp = ntohl(req_packets[i]); temp = ntohl(req_packets[i]);
memcpy(connections[connection_id].req_packets + i, &temp, 4 * number); memcpy(connections[connection_id].req_packets + i, &temp, 4 * number);
} }
@ -595,9 +520,7 @@ int handle_SYNC(uint8_t * packet, uint32_t length, IP_Port source)
{ {
if(!SYNC_valid(length)) if(!SYNC_valid(length))
{
return 1; return 1;
}
int connection = getconnection_id(source); int connection = getconnection_id(source);
uint8_t counter; uint8_t counter;
uint32_t temp; uint32_t temp;
@ -611,21 +534,13 @@ int handle_SYNC(uint8_t * packet, uint32_t length, IP_Port source)
memcpy(&temp,packet + 6, 4); memcpy(&temp,packet + 6, 4);
sent_packetnum = ntohl(temp); sent_packetnum = ntohl(temp);
if(number != 0) if(number != 0)
{
memcpy(req_packets, packet + 10, 4 * number); memcpy(req_packets, packet + 10, 4 * number);
}
if(connection == -1) if(connection == -1)
{
return handle_SYNC1(source, recv_packetnum, sent_packetnum); return handle_SYNC1(source, recv_packetnum, sent_packetnum);
}
if(connections[connection].status == 2) if(connections[connection].status == 2)
{
return handle_SYNC2(connection, counter, recv_packetnum, sent_packetnum); return handle_SYNC2(connection, counter, recv_packetnum, sent_packetnum);
}
if(connections[connection].status == 3) if(connections[connection].status == 3)
{
return handle_SYNC3(connection, counter, recv_packetnum, sent_packetnum, req_packets, number); return handle_SYNC3(connection, counter, recv_packetnum, sent_packetnum, req_packets, number);
}
return 0; return 0;
} }
@ -634,37 +549,26 @@ int handle_SYNC(uint8_t * packet, uint32_t length, IP_Port source)
int add_recv(int connection_id, uint32_t data_num, uint8_t * data, uint16_t size) int add_recv(int connection_id, uint32_t data_num, uint8_t * data, uint16_t size)
{ {
if(size > MAX_DATA_SIZE) if(size > MAX_DATA_SIZE)
{
return 1; return 1;
}
uint32_t i; uint32_t i;
uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM; uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM;
uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum; uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum;
for(i = connections[connection_id].recv_packetnum; i != maxnum; ++i) for(i = connections[connection_id].recv_packetnum; i != maxnum; ++i) {
{ if(i == data_num) {
if(i == data_num)
{
memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size); memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size);
connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size; connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size;
connections[connection_id].last_recvdata = current_time(); connections[connection_id].last_recvdata = current_time();
if(sent_packet < BUFFER_PACKET_NUM) if(sent_packet < BUFFER_PACKET_NUM)
{
connections[connection_id].osent_packetnum = data_num; connections[connection_id].osent_packetnum = data_num;
}
break; break;
} }
} }
for(i = connections[connection_id].recv_packetnum; i != maxnum; ++i) for(i = connections[connection_id].recv_packetnum; i != maxnum; ++i) {
{
if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0) if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0)
{
connections[connection_id].recv_packetnum = i; connections[connection_id].recv_packetnum = i;
}
else else
{
break; break;
}
} }
return 0; return 0;
@ -673,54 +577,43 @@ int add_recv(int connection_id, uint32_t data_num, uint8_t * data, uint16_t size
int handle_data(uint8_t * packet, uint32_t length, IP_Port source) int handle_data(uint8_t * packet, uint32_t length, IP_Port source)
{ {
int connection = getconnection_id(source); int connection = getconnection_id(source);
if(connection == -1) if(connection == -1)
{
return 1; return 1;
}
if(connections[connection].status != 3) /* Drop the data packet if connection is not connected. */ if(connections[connection].status != 3) /* Drop the data packet if connection is not connected. */
{
return 1; return 1;
}
if(length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) if(length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1)
{
return 1; return 1;
}
uint32_t temp; uint32_t temp;
uint32_t number; uint32_t number;
uint16_t size = length - 1 - 4; uint16_t size = length - 1 - 4;
memcpy(&temp, packet + 1, 4); memcpy(&temp, packet + 1, 4);
number = ntohl(temp); number = ntohl(temp);
return add_recv(connection, number, packet + 5, size); return add_recv(connection, number, packet + 5, size);
} }
/* END of packet handling functions */ /* END of packet handling functions */
int LosslessUDP_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) int LosslessUDP_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
{ {
switch (packet[0]) { switch (packet[0]) {
case 16: case 16:
return handle_handshake(packet, length, source); return handle_handshake(packet, length, source);
case 17: case 17:
return handle_SYNC(packet, length, source); return handle_SYNC(packet, length, source);
case 18: case 18:
return handle_data(packet, length, source); return handle_data(packet, length, source);
default: default:
return 1; return 1;
} }
return 0; return 0;
} }
/* Send handshake requests /* Send handshake requests
@ -729,28 +622,20 @@ void doNew()
{ {
uint32_t i; uint32_t i;
uint64_t temp_time = current_time(); uint64_t temp_time = current_time();
for(i = 0; i < MAX_CONNECTIONS; ++i) for(i = 0; i < MAX_CONNECTIONS; ++i) {
{
if(connections[i].status == 1) if(connections[i].status == 1)
{ if((connections[i].last_sent + (1000000UL/connections[i].SYNC_rate)) <= temp_time) {
if((connections[i].last_sent + (1000000UL/connections[i].SYNC_rate)) <= temp_time)
{
send_handshake(connections[i].ip_port, connections[i].handshake_id1, 0); send_handshake(connections[i].ip_port, connections[i].handshake_id1, 0);
connections[i].last_sent = temp_time; connections[i].last_sent = temp_time;
} }
}
/* kill all timed out connections */ /* kill all timed out connections */
if( connections[i].status > 0 && (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time && if( connections[i].status > 0 && (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time &&
connections[i].status != 4) connections[i].status != 4)
{
/* kill_connection(i); */ /* kill_connection(i); */
connections[i].status = 4; connections[i].status = 4;
}
if(connections[i].status > 0 && connections[i].killat < temp_time) if(connections[i].status > 0 && connections[i].killat < temp_time)
{
kill_connection(i); kill_connection(i);
}
} }
} }
@ -758,16 +643,12 @@ void doSYNC()
{ {
uint32_t i; uint32_t i;
uint64_t temp_time = current_time(); uint64_t temp_time = current_time();
for(i = 0; i < MAX_CONNECTIONS; ++i) for(i = 0; i < MAX_CONNECTIONS; ++i) {
{
if(connections[i].status == 2 || connections[i].status == 3) if(connections[i].status == 2 || connections[i].status == 3)
{ if((connections[i].last_SYNC + (1000000UL/connections[i].SYNC_rate)) <= temp_time) {
if((connections[i].last_SYNC + (1000000UL/connections[i].SYNC_rate)) <= temp_time)
{
send_SYNC(i); send_SYNC(i);
connections[i].last_SYNC = temp_time; connections[i].last_SYNC = temp_time;
} }
}
} }
} }
@ -777,19 +658,12 @@ void doData()
uint64_t j; uint64_t j;
uint64_t temp_time = current_time(); uint64_t temp_time = current_time();
for(i = 0; i < MAX_CONNECTIONS; ++i) for(i = 0; i < MAX_CONNECTIONS; ++i)
{
if(connections[i].status == 3 && sendqueue(i) != 0) if(connections[i].status == 3 && sendqueue(i) != 0)
{ if((connections[i].last_sent + (1000000UL/connections[i].data_rate)) <= temp_time) {
if((connections[i].last_sent + (1000000UL/connections[i].data_rate)) <= temp_time)
{
for(j = connections[i].last_sent; j < temp_time; j += (1000000UL/connections[i].data_rate)) for(j = connections[i].last_sent; j < temp_time; j += (1000000UL/connections[i].data_rate))
{
send_DATA(i); send_DATA(i);
}
connections[i].last_sent = temp_time; connections[i].last_sent = temp_time;
} }
}
}
} }
/* TODO: flow control. /* TODO: flow control.
@ -801,33 +675,22 @@ void adjustRates()
{ {
uint32_t i; uint32_t i;
uint64_t temp_time = current_time(); uint64_t temp_time = current_time();
for(i = 0; i < MAX_CONNECTIONS; ++i) for(i = 0; i < MAX_CONNECTIONS; ++i) {
{
if(connections[i].status == 1 || connections[i].status == 2) if(connections[i].status == 1 || connections[i].status == 2)
{
connections[i].SYNC_rate = MAX_SYNC_RATE; connections[i].SYNC_rate = MAX_SYNC_RATE;
} if(connections[i].status == 3) {
if(connections[i].status == 3) if(sendqueue(i) != 0) {
{
if(sendqueue(i) != 0)
{
connections[i].data_rate = (BUFFER_PACKET_NUM - connections[i].num_req_paquets) * MAX_SYNC_RATE; connections[i].data_rate = (BUFFER_PACKET_NUM - connections[i].num_req_paquets) * MAX_SYNC_RATE;
connections[i].SYNC_rate = MAX_SYNC_RATE; connections[i].SYNC_rate = MAX_SYNC_RATE;
} }
else if(connections[i].last_recvdata + 1000000UL > temp_time) else if(connections[i].last_recvdata + 1000000UL > temp_time)
{
connections[i].SYNC_rate = MAX_SYNC_RATE; connections[i].SYNC_rate = MAX_SYNC_RATE;
}
else else
{
connections[i].SYNC_rate = SYNC_RATE; connections[i].SYNC_rate = SYNC_RATE;
}
} }
} }
} }
/* Call this function a couple times per second /* Call this function a couple times per second
It's the main loop. */ It's the main loop. */
void doLossless_UDP() void doLossless_UDP()
@ -836,6 +699,4 @@ void doLossless_UDP()
doSYNC(); doSYNC();
doData(); doData();
adjustRates(); adjustRates();
} }

View File

@ -1,26 +1,25 @@
/* Lossless_UDP.h /* Lossless_UDP.h
* *
* An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt * An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt
* *
* Copyright (C) 2013 Tox project All Rights Reserved.
Copyright (C) 2013 Tox project All Rights Reserved. *
* This file is part of Tox.
This file is part of Tox. *
* Tox is free software: you can redistribute it and/or modify
Tox is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or
the Free Software Foundation, either version 3 of the License, or * (at your option) any later version.
(at your option) any later version. *
* Tox is distributed in the hope that it will be useful,
Tox is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.
GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License * along with Tox. If not, see <http://www.gnu.org/licenses/>.
along with Tox. If not, see <http://www.gnu.org/licenses/>. *
*/
*/
#ifndef LOSSLESS_UDP_H #ifndef LOSSLESS_UDP_H
#define LOSSLESS_UDP_H #define LOSSLESS_UDP_H
@ -34,8 +33,6 @@ extern "C" {
/* maximum length of the data in the data packets */ /* maximum length of the data in the data packets */
#define MAX_DATA_SIZE 1024 #define MAX_DATA_SIZE 1024
/* Functions */ /* Functions */
/* initialize a new connection to ip_port /* initialize a new connection to ip_port
@ -53,7 +50,6 @@ int getconnection_id(IP_Port ip_port);
return -1 if there are no new incoming connections in the list. */ return -1 if there are no new incoming connections in the list. */
int incoming_connection(); int incoming_connection();
/* return -1 if it could not kill the connection. /* return -1 if it could not kill the connection.
return 0 if killed successfully */ return 0 if killed successfully */
int kill_connection(int connection_id); int kill_connection(int connection_id);
@ -75,21 +71,16 @@ char id_packet(int connection_id);
return length of received packet if successful */ return length of received packet if successful */
int read_packet(int connection_id, uint8_t * data); int read_packet(int connection_id, uint8_t * data);
/* return 0 if data could not be put in packet queue /* return 0 if data could not be put in packet queue
return 1 if data was put into the queue */ return 1 if data was put into the queue */
int write_packet(int connection_id, uint8_t * data, uint32_t length); int write_packet(int connection_id, uint8_t * data, uint32_t length);
/* returns the number of packets in the queue waiting to be successfully sent. */ /* returns the number of packets in the queue waiting to be successfully sent. */
uint32_t sendqueue(int connection_id); uint32_t sendqueue(int connection_id);
/* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */ /* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */
uint32_t recvqueue(int connection_id); uint32_t recvqueue(int connection_id);
/* check if connection is connected /* check if connection is connected
return 0 no. return 0 no.
return 1 if attempting handshake return 1 if attempting handshake
@ -98,7 +89,6 @@ uint32_t recvqueue(int connection_id);
return 4 if timed out and wating to be killed */ return 4 if timed out and wating to be killed */
int is_connected(int connection_id); int is_connected(int connection_id);
/* Call this function a couple times per second /* Call this function a couple times per second
It's the main loop. */ It's the main loop. */
void doLossless_UDP(); void doLossless_UDP();

View File

@ -1,26 +1,25 @@
/* Messenger.c /* Messenger.c
* *
* An implementation of a simple text chat only messenger on the tox network core. * An implementation of a simple text chat only messenger on the tox network core.
* *
* Copyright (C) 2013 Tox project All Rights Reserved.
Copyright (C) 2013 Tox project All Rights Reserved. *
* This file is part of Tox.
This file is part of Tox. *
* Tox is free software: you can redistribute it and/or modify
Tox is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or
the Free Software Foundation, either version 3 of the License, or * (at your option) any later version.
(at your option) any later version. *
* Tox is distributed in the hope that it will be useful,
Tox is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.
GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License * along with Tox. If not, see <http://www.gnu.org/licenses/>.
along with Tox. If not, see <http://www.gnu.org/licenses/>. *
*/
*/
#include "Messenger.h" #include "Messenger.h"
#define MIN(a,b) (((a)<(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b))
@ -39,8 +38,6 @@ typedef struct
uint8_t userstatus_sent; uint8_t userstatus_sent;
uint16_t info_size; /* length of the info */ uint16_t info_size; /* length of the info */
}Friend; }Friend;
uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
@ -58,26 +55,20 @@ static uint32_t numfriends;
0 if we are offline 0 if we are offline
static uint8_t online; */ static uint8_t online; */
/* return the friend id associated to that public key. /* return the friend id associated to that public key.
return -1 if no such friend */ return -1 if no such friend */
int getfriend_id(uint8_t * client_id) int getfriend_id(uint8_t * client_id)
{ {
uint32_t i; uint32_t i;
for(i = 0; i < numfriends; ++i) for(i = 0; i < numfriends; ++i)
{
if(friendlist[i].status > 0) if(friendlist[i].status > 0)
{
if(memcmp(client_id, friendlist[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) if(memcmp(client_id, friendlist[i].client_id, crypto_box_PUBLICKEYBYTES) == 0)
{
return i; return i;
}
}
}
return -1; return -1;
} }
/* copies the public key associated to that friend id into client_id buffer. /* copies the public key associated to that friend id into client_id buffer.
make sure that client_id is of size CLIENT_ID_SIZE. make sure that client_id is of size CLIENT_ID_SIZE.
return 0 if success return 0 if success
@ -85,19 +76,16 @@ int getfriend_id(uint8_t * client_id)
int getclient_id(int friend_id, uint8_t * client_id) int getclient_id(int friend_id, uint8_t * client_id)
{ {
if(friend_id >= numfriends || friend_id < 0) if(friend_id >= numfriends || friend_id < 0)
{
return -1; return -1;
}
if(friendlist[friend_id].status > 0) if(friendlist[friend_id].status > 0) {
{
memcpy(client_id, friendlist[friend_id].client_id, CLIENT_ID_SIZE); memcpy(client_id, friendlist[friend_id].client_id, CLIENT_ID_SIZE);
return 0; return 0;
} }
return -1; return -1;
} }
/* add a friend /* add a friend
set the data that will be sent along with friend request set the data that will be sent along with friend request
client_id is the client id of the friend client_id is the client id of the friend
@ -108,17 +96,11 @@ int m_addfriend(uint8_t * client_id, uint8_t * data, uint16_t length)
{ {
if(length == 0 || length >= if(length == 0 || length >=
(MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES))
{
return -1; return -1;
}
if(memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) if(memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0)
{
return -1; return -1;
}
if(getfriend_id(client_id) != -1) if(getfriend_id(client_id) != -1)
{
return -1; return -1;
}
uint32_t i; uint32_t i;
for(i = 0; i <= numfriends; ++i) for(i = 0; i <= numfriends; ++i)
{ {
@ -144,9 +126,7 @@ int m_addfriend(uint8_t * client_id, uint8_t * data, uint16_t length)
int m_addfriend_norequest(uint8_t * client_id) int m_addfriend_norequest(uint8_t * client_id)
{ {
if(getfriend_id(client_id) != -1) if(getfriend_id(client_id) != -1)
{
return -1; return -1;
}
uint32_t i; uint32_t i;
for(i = 0; i <= numfriends; ++i) for(i = 0; i <= numfriends; ++i)
{ {
@ -172,9 +152,7 @@ int m_addfriend_norequest(uint8_t * client_id)
int m_delfriend(int friendnumber) int m_delfriend(int friendnumber)
{ {
if(friendnumber >= numfriends || friendnumber < 0) if(friendnumber >= numfriends || friendnumber < 0)
{
return -1; return -1;
}
DHT_delfriend(friendlist[friendnumber].client_id); DHT_delfriend(friendlist[friendnumber].client_id);
crypto_kill(friendlist[friendnumber].crypt_connection_id); crypto_kill(friendlist[friendnumber].crypt_connection_id);
@ -182,17 +160,12 @@ int m_delfriend(int friendnumber)
memset(&friendlist[friendnumber], 0, sizeof(Friend)); memset(&friendlist[friendnumber], 0, sizeof(Friend));
uint32_t i; uint32_t i;
for(i = numfriends; i != 0; --i) for(i = numfriends; i != 0; --i)
{
if(friendlist[i].status != 0) if(friendlist[i].status != 0)
{
break; break;
}
}
numfriends = i; numfriends = i;
return 0; return 0;
} }
/* return 4 if friend is online /* return 4 if friend is online
return 3 if friend is confirmed return 3 if friend is confirmed
return 2 if the friend request was sent return 2 if the friend request was sent
@ -201,27 +174,20 @@ int m_delfriend(int friendnumber)
int m_friendstatus(int friendnumber) int m_friendstatus(int friendnumber)
{ {
if(friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS) if(friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS)
{
return 0; return 0;
}
return friendlist[friendnumber].status; return friendlist[friendnumber].status;
} }
/* send a text chat message to an online friend /* send a text chat message to an online friend
return 1 if packet was successfully put into the send queue return 1 if packet was successfully put into the send queue
return 0 if it was not */ return 0 if it was not */
int m_sendmessage(int friendnumber, uint8_t * message, uint32_t length) int m_sendmessage(int friendnumber, uint8_t * message, uint32_t length)
{ {
if(friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS) if(friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS)
{
return 0; return 0;
}
if(length >= MAX_DATA_SIZE || friendlist[friendnumber].status != 4) if(length >= MAX_DATA_SIZE || friendlist[friendnumber].status != 4)
/* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */ /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */
{
return 0; return 0;
}
uint8_t temp[MAX_DATA_SIZE]; uint8_t temp[MAX_DATA_SIZE];
temp[0] = PACKET_ID_MESSAGE; temp[0] = PACKET_ID_MESSAGE;
memcpy(temp + 1, message, length); memcpy(temp + 1, message, length);
@ -240,18 +206,14 @@ static int m_sendname(int friendnumber, uint8_t * name)
/* set the name of a friend /* set the name of a friend
return 0 if success return 0 if success
return -1 if failure */ return -1 if failure */
static int setfriendname(int friendnumber, uint8_t * name) static int setfriendname(int friendnumber, uint8_t * name)
{ {
if(friendnumber >= numfriends || friendnumber < 0) if(friendnumber >= numfriends || friendnumber < 0)
{
return -1; return -1;
}
memcpy(friendlist[friendnumber].name, name, MAX_NAME_LENGTH); memcpy(friendlist[friendnumber].name, name, MAX_NAME_LENGTH);
return 0; return 0;
} }
/* Set our nickname /* Set our nickname
name must be a string of maximum MAX_NAME_LENGTH length. name must be a string of maximum MAX_NAME_LENGTH length.
return 0 if success return 0 if success
@ -259,15 +221,11 @@ static int setfriendname(int friendnumber, uint8_t * name)
int setname(uint8_t * name, uint16_t length) int setname(uint8_t * name, uint16_t length)
{ {
if(length > MAX_NAME_LENGTH) if(length > MAX_NAME_LENGTH)
{
return -1; return -1;
}
memcpy(self_name, name, length); memcpy(self_name, name, length);
uint32_t i; uint32_t i;
for(i = 0; i < numfriends; ++i) for(i = 0; i < numfriends; ++i)
{
friendlist[i].name_sent = 0; friendlist[i].name_sent = 0;
}
return 0; return 0;
} }
@ -279,9 +237,7 @@ int setname(uint8_t * name, uint16_t length)
int getname(int friendnumber, uint8_t * name) int getname(int friendnumber, uint8_t * name)
{ {
if(friendnumber >= numfriends || friendnumber < 0) if(friendnumber >= numfriends || friendnumber < 0)
{
return -1; return -1;
}
memcpy(name, friendlist[friendnumber].name, MAX_NAME_LENGTH); memcpy(name, friendlist[friendnumber].name, MAX_NAME_LENGTH);
return 0; return 0;
} }
@ -289,9 +245,7 @@ int getname(int friendnumber, uint8_t * name)
int m_set_userstatus(uint8_t *status, uint16_t length) int m_set_userstatus(uint8_t *status, uint16_t length)
{ {
if(length > MAX_USERSTATUS_LENGTH) if(length > MAX_USERSTATUS_LENGTH)
{
return -1; return -1;
}
uint8_t *newstatus = calloc(length, 1); uint8_t *newstatus = calloc(length, 1);
memcpy(newstatus, status, length); memcpy(newstatus, status, length);
free(self_userstatus); free(self_userstatus);
@ -300,9 +254,7 @@ int m_set_userstatus(uint8_t *status, uint16_t length)
uint32_t i; uint32_t i;
for(i = 0; i < numfriends; ++i) for(i = 0; i < numfriends; ++i)
{
friendlist[i].userstatus_sent = 0; friendlist[i].userstatus_sent = 0;
}
return 0; return 0;
} }
@ -311,9 +263,7 @@ int m_set_userstatus(uint8_t *status, uint16_t length)
int m_get_userstatus_size(int friendnumber) int m_get_userstatus_size(int friendnumber)
{ {
if(friendnumber >= numfriends || friendnumber < 0) if(friendnumber >= numfriends || friendnumber < 0)
{
return -1; return -1;
}
return friendlist[friendnumber].userstatus_length; return friendlist[friendnumber].userstatus_length;
} }
@ -322,9 +272,7 @@ int m_get_userstatus_size(int friendnumber)
int m_copy_userstatus(int friendnumber, uint8_t * buf, uint32_t maxlen) int m_copy_userstatus(int friendnumber, uint8_t * buf, uint32_t maxlen)
{ {
if(friendnumber >= numfriends || friendnumber < 0) if(friendnumber >= numfriends || friendnumber < 0)
{
return -1; return -1;
}
memset(buf, 0, maxlen); memset(buf, 0, maxlen);
memcpy(buf, friendlist[friendnumber].userstatus, MIN(maxlen, MAX_USERSTATUS_LENGTH) - 1); memcpy(buf, friendlist[friendnumber].userstatus, MIN(maxlen, MAX_USERSTATUS_LENGTH) - 1);
return 0; return 0;
@ -343,9 +291,7 @@ static int send_userstatus(int friendnumber, uint8_t * status, uint16_t length)
static int set_friend_userstatus(int friendnumber, uint8_t * status, uint16_t length) static int set_friend_userstatus(int friendnumber, uint8_t * status, uint16_t length)
{ {
if(friendnumber >= numfriends || friendnumber < 0) if(friendnumber >= numfriends || friendnumber < 0)
{
return -1; return -1;
}
uint8_t *newstatus = calloc(length, 1); uint8_t *newstatus = calloc(length, 1);
memcpy(newstatus, status, length); memcpy(newstatus, status, length);
free(friendlist[friendnumber].userstatus); free(friendlist[friendnumber].userstatus);
@ -353,17 +299,15 @@ static int set_friend_userstatus(int friendnumber, uint8_t * status, uint16_t le
friendlist[friendnumber].userstatus_length = length; friendlist[friendnumber].userstatus_length = length;
return 0; return 0;
} }
/*
static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); /* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t);
static uint8_t friend_request_isset = 0; static uint8_t friend_request_isset = 0; */
*/
/* set the function that will be executed when a friend request is received. */ /* set the function that will be executed when a friend request is received. */
void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)) void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t))
{ {
callback_friendrequest(function); callback_friendrequest(function);
} }
static void (*friend_message)(int, uint8_t *, uint16_t); static void (*friend_message)(int, uint8_t *, uint16_t);
static uint8_t friend_message_isset = 0; static uint8_t friend_message_isset = 0;
@ -374,7 +318,6 @@ void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t))
friend_message_isset = 1; friend_message_isset = 1;
} }
static void (*friend_namechange)(int, uint8_t *, uint16_t); static void (*friend_namechange)(int, uint8_t *, uint16_t);
static uint8_t friend_namechange_isset = 0; static uint8_t friend_namechange_isset = 0;
void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)) void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t))
@ -402,9 +345,9 @@ int initMessenger()
ip.i = 0; ip.i = 0;
if(init_networking(ip,PORT) == -1) if(init_networking(ip,PORT) == -1)
return -1; return -1;
return 0; return 0;
} }
static void doFriends() static void doFriends()
@ -417,16 +360,12 @@ static void doFriends()
if(friendlist[i].status == 1) if(friendlist[i].status == 1)
{ {
int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
if(fr == 0)/*TODO: This needs to be fixed so that it sends the friend requests a couple of times in case if(fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case
of packet loss*/ of packet loss */
{
friendlist[i].status = 2; friendlist[i].status = 2;
}
else else
if(fr > 0) if(fr > 0)
{
friendlist[i].status = 2; friendlist[i].status = 2;
}
} }
if(friendlist[i].status == 2 || friendlist[i].status == 3) /* friend is not online */ if(friendlist[i].status == 2 || friendlist[i].status == 3) /* friend is not online */
{ {
@ -436,12 +375,10 @@ static void doFriends()
{ {
send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
friendlist[i].friend_request_id = unix_time(); friendlist[i].friend_request_id = unix_time();
} }
} }
IP_Port friendip = DHT_getfriendip(friendlist[i].client_id); IP_Port friendip = DHT_getfriendip(friendlist[i].client_id);
switch(is_cryptoconnected(friendlist[i].crypt_connection_id)) switch(is_cryptoconnected(friendlist[i].crypt_connection_id)) {
{
case 0: case 0:
if (friendip.ip.i > 1) if (friendip.ip.i > 1)
friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip); friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip);
@ -460,19 +397,11 @@ static void doFriends()
while(friendlist[i].status == 4) /* friend is online */ while(friendlist[i].status == 4) /* friend is online */
{ {
if(friendlist[i].name_sent == 0) if(friendlist[i].name_sent == 0)
{
if(m_sendname(i, self_name)) if(m_sendname(i, self_name))
{
friendlist[i].name_sent = 1; friendlist[i].name_sent = 1;
}
}
if(friendlist[i].userstatus_sent == 0) if(friendlist[i].userstatus_sent == 0)
{
if(send_userstatus(i, self_userstatus, self_userstatus_len)) if(send_userstatus(i, self_userstatus, self_userstatus_len))
{
friendlist[i].userstatus_sent = 1; friendlist[i].userstatus_sent = 1;
}
}
len = read_cryptpacket(friendlist[i].crypt_connection_id, temp); len = read_cryptpacket(friendlist[i].crypt_connection_id, temp);
if(len > 0) if(len > 0)
{ {
@ -500,9 +429,7 @@ static void doFriends()
} }
case PACKET_ID_MESSAGE: { case PACKET_ID_MESSAGE: {
if(friend_message_isset) if(friend_message_isset)
{
(*friend_message)(i, temp + 1, len - 1); (*friend_message)(i, temp + 1, len - 1);
}
break; break;
} }
} }
@ -521,8 +448,6 @@ static void doFriends()
} }
} }
static void doInbound() static void doInbound()
{ {
uint8_t secret_nonce[crypto_box_NONCEBYTES]; uint8_t secret_nonce[crypto_box_NONCEBYTES];
@ -543,6 +468,22 @@ static void doInbound()
} }
} }
/*Interval in seconds between LAN discovery packet sending*/
#define LAN_DISCOVERY_INTERVAL 60
static uint32_t last_LANdiscovery;
/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/
static void LANdiscovery()
{
if(last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time())
{
send_LANdiscovery(htons(PORT));
last_LANdiscovery = unix_time();
}
}
/* the main loop that needs to be run at least 200 times per second. */ /* the main loop that needs to be run at least 200 times per second. */
void doMessenger() void doMessenger()
{ {
@ -554,21 +495,19 @@ void doMessenger()
#ifdef DEBUG #ifdef DEBUG
/* if(rand() % 3 != 1) //simulate packet loss */ /* if(rand() % 3 != 1) //simulate packet loss */
/* { */ /* { */
if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port) && friendreq_handlepacket(data, length, ip_port)) if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port) &&
{ friendreq_handlepacket(data, length, ip_port) && LANdiscovery_handlepacket(data, length, ip_port))
/* if packet is discarded */ /* if packet is discarded */
printf("Received unhandled packet with length: %u\n", length); printf("Received unhandled packet with length: %u\n", length);
}
else else
{
printf("Received handled packet with length: %u\n", length); printf("Received handled packet with length: %u\n", length);
}
/* } */ /* } */
printf("Status: %u %u %u\n",friendlist[0].status ,is_cryptoconnected(friendlist[0].crypt_connection_id), friendlist[0].crypt_connection_id); printf("Status: %u %u %u\n",friendlist[0].status ,is_cryptoconnected(friendlist[0].crypt_connection_id), friendlist[0].crypt_connection_id);
#else #else
DHT_handlepacket(data, length, ip_port); DHT_handlepacket(data, length, ip_port);
LosslessUDP_handlepacket(data, length, ip_port); LosslessUDP_handlepacket(data, length, ip_port);
friendreq_handlepacket(data, length, ip_port); friendreq_handlepacket(data, length, ip_port);
LANdiscovery_handlepacket(data, length, ip_port);
#endif #endif
} }
@ -577,6 +516,7 @@ void doMessenger()
doNetCrypto(); doNetCrypto();
doInbound(); doInbound();
doFriends(); doFriends();
LANdiscovery();
} }
/* returns the size of the messenger data (for saving) */ /* returns the size of the messenger data (for saving) */
@ -606,13 +546,9 @@ void Messenger_save(uint8_t * data)
int Messenger_load(uint8_t * data, uint32_t length) int Messenger_load(uint8_t * data, uint32_t length)
{ {
if(length == ~0) if(length == ~0)
{
return -1; return -1;
}
if(length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2) if(length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2)
{
return -1; return -1;
}
length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2; length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2;
load_keys(data); load_keys(data);
data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
@ -621,21 +557,15 @@ int Messenger_load(uint8_t * data, uint32_t length)
data += sizeof(size); data += sizeof(size);
if(length < size) if(length < size)
{
return -1; return -1;
}
length -= size; length -= size;
if(DHT_load(data, size) == -1) if(DHT_load(data, size) == -1)
{
return -1; return -1;
}
data += size; data += size;
memcpy(&size, data, sizeof(size)); memcpy(&size, data, sizeof(size));
data += sizeof(size); data += sizeof(size);
if(length != size || length % sizeof(Friend) != 0) if(length != size || length % sizeof(Friend) != 0)
{
return -1; return -1;
}
Friend * temp = malloc(size); Friend * temp = malloc(size);
memcpy(temp, data, size); memcpy(temp, data, size);

View File

@ -1,35 +1,35 @@
/* Messenger.h /* Messenger.h
* *
* An implementation of a simple text chat only messenger on the tox network core. * An implementation of a simple text chat only messenger on the tox network core.
* *
* NOTE: All the text in the messages must be encoded using UTF-8 * NOTE: All the text in the messages must be encoded using UTF-8
*
Copyright (C) 2013 Tox project All Rights Reserved. * Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/
This file is part of Tox.
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/>.
*/
#ifndef MESSENGER_H #ifndef MESSENGER_H
#define MESSENGER_H #define MESSENGER_H
#include "net_crypto.h" #include "net_crypto.h"
#include "DHT.h" #include "DHT.h"
#include "friend_requests.h" #include "friend_requests.h"
#include "LAN_discovery.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -79,7 +79,6 @@ int m_delfriend(int friendnumber);
return 0 if there is no friend with that number */ return 0 if there is no friend with that number */
int m_friendstatus(int friendnumber); int m_friendstatus(int friendnumber);
/* send a text chat message to an online friend /* send a text chat message to an online friend
returns 1 if packet was successfully put into the send queue returns 1 if packet was successfully put into the send queue
return 0 if it was not */ return 0 if it was not */
@ -91,7 +90,6 @@ int m_sendmessage(int friendnumber, uint8_t * message, uint32_t length);
return -1 if failure */ return -1 if failure */
int setname(uint8_t * name, uint16_t length); int setname(uint8_t * name, uint16_t length);
/* get name of friendnumber /* get name of friendnumber
put it in name put it in name
name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
@ -117,7 +115,6 @@ int m_copy_userstatus(int friendnumber, uint8_t * buf, uint32_t maxlen);
function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */
void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t));
/* set the function that will be executed when a message from a friend is received. /* set the function that will be executed when a message from a friend is received.
function format is: function(int friendnumber, uint8_t * message, uint32_t length) */ function format is: function(int friendnumber, uint8_t * message, uint32_t length) */
void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)); void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t));
@ -137,11 +134,9 @@ void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t));
returns -1 if there are problems */ returns -1 if there are problems */
int initMessenger(); int initMessenger();
/* the main loop that needs to be run at least 200 times per second */ /* the main loop that needs to be run at least 200 times per second */
void doMessenger(); void doMessenger();
/* SAVING AND LOADING FUNCTIONS: */ /* SAVING AND LOADING FUNCTIONS: */
/* returns the size of the messenger data (for saving) */ /* returns the size of the messenger data (for saving) */

View File

@ -2,13 +2,29 @@
* *
* Handle friend requests. * Handle friend requests.
* *
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/ */
#include "friend_requests.h" #include "friend_requests.h"
uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
/* Try to send a friendrequest to peer with public_key /* Try to send a friendrequest to peer with public_key
data is the data in the request and length is the length. data is the data in the request and length is the length.
return -1 if failure. return -1 if failure.
@ -18,33 +34,30 @@ int send_friendrequest(uint8_t * public_key, uint8_t * data, uint32_t length)
{ {
uint8_t packet[MAX_DATA_SIZE]; uint8_t packet[MAX_DATA_SIZE];
int len = create_request(packet, public_key, data, length, 32); /* 32 is friend request packet id */ int len = create_request(packet, public_key, data, length, 32); /* 32 is friend request packet id */
if(len == -1) if(len == -1)
{
return -1; return -1;
}
IP_Port ip_port = DHT_getfriendip(public_key); IP_Port ip_port = DHT_getfriendip(public_key);
if(ip_port.ip.i == 1) if(ip_port.ip.i == 1)
{
return -1; return -1;
}
if(ip_port.ip.i != 0) if(ip_port.ip.i != 0)
{ {
if(sendpacket(ip_port, packet, len) != -1) if(sendpacket(ip_port, packet, len) != -1)
{
return 0; return 0;
}
return -1; return -1;
} }
int num = route_tofriend(public_key, packet, len); int num = route_tofriend(public_key, packet, len);
if(num == 0) if(num == 0)
{
return -1; return -1;
}
return num; return num;
} }
static void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t); static void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t);
static uint8_t handle_friendrequest_isset = 0; static uint8_t handle_friendrequest_isset = 0;
@ -56,6 +69,38 @@ void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t))
} }
/*NOTE: the following is just a temporary fix for the multiple friend requests recieved at the same time problem
TODO: Make this better (This will most likely tie in with the way we will handle spam.)*/
#define MAX_RECIEVED_STORED 32
static uint8_t recieved_requests[MAX_RECIEVED_STORED][crypto_box_PUBLICKEYBYTES];
static uint16_t recieved_requests_index;
/*Add to list of recieved friend requests*/
static void addto_recievedlist(uint8_t * client_id)
{
if(recieved_requests_index >= MAX_RECIEVED_STORED)
recieved_requests_index = 0;
memcpy(recieved_requests[recieved_requests_index], client_id, crypto_box_PUBLICKEYBYTES);
++recieved_requests_index;
}
/* Check if a friend request was already recieved
return 0 if not, 1 if we did */
static int request_recieved(uint8_t * client_id)
{
uint32_t i;
for(i = 0; i < MAX_RECIEVED_STORED; ++i)
if(memcmp(recieved_requests[i], client_id, crypto_box_PUBLICKEYBYTES) == 0)
return 1;
return 0;
}
int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
{ {
@ -63,31 +108,27 @@ int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
{ {
if(length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && if(length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING &&
length > MAX_DATA_SIZE + ENCRYPTION_PADDING) length > MAX_DATA_SIZE + ENCRYPTION_PADDING)
{
return 1; return 1;
} if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) /* check if request is for us. */
if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0)//check if request is for us.
{ {
if(handle_friendrequest_isset == 0) if(handle_friendrequest_isset == 0)
{
return 1; return 1;
}
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t public_key[crypto_box_PUBLICKEYBYTES];
uint8_t data[MAX_DATA_SIZE]; uint8_t data[MAX_DATA_SIZE];
int len = handle_request(public_key, data, packet, length); int len = handle_request(public_key, data, packet, length);
if(len == -1) if(len == -1)
{
return 1; return 1;
} if(request_recieved(public_key))
return 1;
addto_recievedlist(public_key);
(*handle_friendrequest)(public_key, data, len); (*handle_friendrequest)(public_key, data, len);
} }
else//if request is not for us, try routing it. else /* if request is not for us, try routing it. */
{
if(route_packet(packet + 1, packet, length) == length) if(route_packet(packet + 1, packet, length) == length)
{
return 0; return 0;
}
}
} }
return 1; return 1;
} }

View File

@ -2,13 +2,28 @@
* *
* Handle friend requests. * Handle friend requests.
* *
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/ */
#ifndef FRIEND_REQUESTS_H #ifndef FRIEND_REQUESTS_H
#define FRIEND_REQUESTS_H #define FRIEND_REQUESTS_H
#include "DHT.h" #include "DHT.h"
#include "net_crypto.h" #include "net_crypto.h"
@ -20,7 +35,6 @@ extern "C" {
data is the data in the request and length is the length. */ data is the data in the request and length is the length. */
int send_friendrequest(uint8_t * public_key, uint8_t * data, uint32_t length); int send_friendrequest(uint8_t * public_key, uint8_t * data, uint32_t length);
/* set the function that will be executed when a friend request for us is received. /* set the function that will be executed when a friend request for us is received.
function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */
void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t));
@ -30,8 +44,6 @@ void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t));
return 1 if it didn't handle the packet or if the packet was shit. */ return 1 if it didn't handle the packet or if the packet was shit. */
int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source); int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,38 +1,35 @@
/* net_crypto.c /* net_crypto.c
* *
* Functions for the core network crypto. * Functions for the core network crypto.
* See also: docs/Crypto.txt * See also: docs/Crypto.txt
* *
* NOTE: This code has to be perfect. We don't mess around with encryption. * NOTE: This code has to be perfect. We don't mess around with encryption.
* *
* Copyright (C) 2013 Tox project All Rights Reserved.
Copyright (C) 2013 Tox project All Rights Reserved. *
* This file is part of Tox.
This file is part of Tox. *
* Tox is free software: you can redistribute it and/or modify
Tox is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or
the Free Software Foundation, either version 3 of the License, or * (at your option) any later version.
(at your option) any later version. *
* Tox is distributed in the hope that it will be useful,
Tox is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.
GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License * along with Tox. If not, see <http://www.gnu.org/licenses/>.
along with Tox. If not, see <http://www.gnu.org/licenses/>. *
*/
*/
#include "net_crypto.h" #include "net_crypto.h"
/* Our public and secret keys. */ /* Our public and secret keys. */
uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
typedef struct typedef struct
{ {
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* the real public key of the peer. */ uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* the real public key of the peer. */
@ -65,9 +62,7 @@ int encrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce,
uint8_t * plain, uint32_t length, uint8_t * encrypted) uint8_t * plain, uint32_t length, uint8_t * encrypted)
{ {
if(length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE || length == 0) if(length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE || length == 0)
{
return -1; return -1;
}
uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES] = {0}; uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES] = {0};
uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES]; uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES];
@ -79,9 +74,8 @@ int encrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce,
/* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero */ /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero */
if(memcmp(temp_encrypted, zeroes, crypto_box_BOXZEROBYTES) != 0) if(memcmp(temp_encrypted, zeroes, crypto_box_BOXZEROBYTES) != 0)
{
return -1; return -1;
}
/* unpad the encrypted message */ /* unpad the encrypted message */
memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES);
return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES; return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES;
@ -95,9 +89,8 @@ int decrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce,
uint8_t * encrypted, uint32_t length, uint8_t * plain) uint8_t * encrypted, uint32_t length, uint8_t * plain)
{ {
if(length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) if(length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES)
{
return -1; return -1;
}
uint8_t temp_plain[MAX_DATA_SIZE - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES]; uint8_t temp_plain[MAX_DATA_SIZE - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES];
uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0}; uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0};
uint8_t zeroes[crypto_box_ZEROBYTES] = {0}; uint8_t zeroes[crypto_box_ZEROBYTES] = {0};
@ -106,14 +99,12 @@ int decrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce,
if(crypto_box_open(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, if(crypto_box_open(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES,
nonce, public_key, secret_key) == -1) nonce, public_key, secret_key) == -1)
{
return -1; return -1;
}
/* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero */ /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero */
if(memcmp(temp_plain, zeroes, crypto_box_ZEROBYTES) != 0) if(memcmp(temp_plain, zeroes, crypto_box_ZEROBYTES) != 0)
{
return -1; return -1;
}
/* unpad the plain message */ /* unpad the plain message */
memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES); memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES);
return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES;
@ -123,13 +114,10 @@ int decrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce,
void increment_nonce(uint8_t * nonce) void increment_nonce(uint8_t * nonce)
{ {
uint32_t i; uint32_t i;
for(i = 0; i < crypto_box_NONCEBYTES; ++i) for(i = 0; i < crypto_box_NONCEBYTES; ++i) {
{
++nonce[i]; ++nonce[i];
if(nonce[i] != 0) if(nonce[i] != 0)
{
break; break;
}
} }
} }
@ -137,8 +125,7 @@ void increment_nonce(uint8_t * nonce)
void random_nonce(uint8_t * nonce) void random_nonce(uint8_t * nonce)
{ {
uint32_t i, temp; uint32_t i, temp;
for (i = 0; i < crypto_box_NONCEBYTES / 4; ++i) for (i = 0; i < crypto_box_NONCEBYTES / 4; ++i) {
{
temp = random_int(); temp = random_int();
memcpy(nonce + 4 * i, &temp, 4); memcpy(nonce + 4 * i, &temp, 4);
} }
@ -150,64 +137,44 @@ void random_nonce(uint8_t * nonce)
int read_cryptpacket(int crypt_connection_id, uint8_t * data) int read_cryptpacket(int crypt_connection_id, uint8_t * data)
{ {
if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
{
return 0; return 0;
}
if(crypto_connections[crypt_connection_id].status != 3) if(crypto_connections[crypt_connection_id].status != 3)
{
return 0; return 0;
}
uint8_t temp_data[MAX_DATA_SIZE]; uint8_t temp_data[MAX_DATA_SIZE];
int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data); int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data);
if(length == 0) if(length == 0)
{
return 0; return 0;
}
if(temp_data[0] != 3) if(temp_data[0] != 3)
{
return -1; return -1;
}
int len = decrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, int len = decrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key,
crypto_connections[crypt_connection_id].sessionsecret_key, crypto_connections[crypt_connection_id].sessionsecret_key,
crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data); crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data);
if(len != -1) if(len != -1) {
{
increment_nonce(crypto_connections[crypt_connection_id].recv_nonce); increment_nonce(crypto_connections[crypt_connection_id].recv_nonce);
return len; return len;
} }
return -1; return -1;
} }
/* return 0 if data could not be put in packet queue /* return 0 if data could not be put in packet queue
return 1 if data was put into the queue */ return 1 if data was put into the queue */
int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length) int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length)
{ {
if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
{
return 0; return 0;
}
if(length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) if(length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1)
{
return 0; return 0;
}
if(crypto_connections[crypt_connection_id].status != 3) if(crypto_connections[crypt_connection_id].status != 3)
{
return 0; return 0;
}
uint8_t temp_data[MAX_DATA_SIZE]; uint8_t temp_data[MAX_DATA_SIZE];
int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key,
crypto_connections[crypt_connection_id].sessionsecret_key, crypto_connections[crypt_connection_id].sessionsecret_key,
crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1); crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1);
if(len == -1) if(len == -1)
{
return 0; return 0;
}
temp_data[0] = 3; temp_data[0] = 3;
if(write_packet(crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) if(write_packet(crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0)
{
return 0; return 0;
}
increment_nonce(crypto_connections[crypt_connection_id].sent_nonce); increment_nonce(crypto_connections[crypt_connection_id].sent_nonce);
return 1; return 1;
} }
@ -221,17 +188,13 @@ int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length)
int create_request(uint8_t * packet, uint8_t * public_key, uint8_t * data, uint32_t length, uint8_t request_id) int create_request(uint8_t * packet, uint8_t * public_key, uint8_t * data, uint32_t length, uint8_t request_id)
{ {
if(MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING) if(MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING)
{
return -1; return -1;
}
uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t nonce[crypto_box_NONCEBYTES];
random_nonce(nonce); random_nonce(nonce);
int len = encrypt_data(public_key, self_secret_key, nonce, data, length, int len = encrypt_data(public_key, self_secret_key, nonce, data, length,
1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet);
if(len == -1) if(len == -1)
{
return -1; return -1;
}
packet[0] = request_id; packet[0] = request_id;
memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, self_public_key, crypto_box_PUBLICKEYBYTES); memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, self_public_key, crypto_box_PUBLICKEYBYTES);
@ -257,18 +220,13 @@ int handle_request(uint8_t * public_key, uint8_t * data, uint8_t * packet, uint1
int len1 = decrypt_data(public_key, self_secret_key, nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, int len1 = decrypt_data(public_key, self_secret_key, nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES,
length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), data); length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), data);
if(len1 == -1) if(len1 == -1)
{
return -1; return -1;
}
return len1; return len1;
} }
else else
{
return -1; return -1;
}
} }
/* Send a crypto handshake packet containing an encrypted secret nonce and session public key /* Send a crypto handshake packet containing an encrypted secret nonce and session public key
to peer with connection_id and public_key to peer with connection_id and public_key
the packet is encrypted with a random nonce which is sent in plain text with the packet */ the packet is encrypted with a random nonce which is sent in plain text with the packet */
@ -285,9 +243,7 @@ int send_cryptohandshake(int connection_id, uint8_t * public_key, uint8_t * secr
int len = encrypt_data(public_key, self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, int len = encrypt_data(public_key, self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data);
if(len == -1) if(len == -1)
{
return 0; return 0;
}
temp_data[0] = 2; temp_data[0] = 2;
memcpy(temp_data + 1, self_public_key, crypto_box_PUBLICKEYBYTES); memcpy(temp_data + 1, self_public_key, crypto_box_PUBLICKEYBYTES);
memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
@ -307,9 +263,7 @@ int handle_cryptohandshake(uint8_t * public_key, uint8_t * secret_nonce,
return 0; return 0;
} }
if(data[0] != 2) if(data[0] != 2)
{
return 0; return 0;
}
uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES];
memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES);
@ -319,18 +273,13 @@ int handle_cryptohandshake(uint8_t * public_key, uint8_t * secret_nonce,
crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp); crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp);
if(len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES) if(len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES)
{
return 0; return 0;
}
memcpy(secret_nonce, temp, crypto_box_NONCEBYTES); memcpy(secret_nonce, temp, crypto_box_NONCEBYTES);
memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES);
return 1; return 1;
} }
/* get crypto connection id from public key of peer /* get crypto connection id from public key of peer
return -1 if there are no connections like we are looking for return -1 if there are no connections like we are looking for
return id if it found it */ return id if it found it */
@ -338,19 +287,12 @@ int getcryptconnection_id(uint8_t * public_key)
{ {
uint32_t i; uint32_t i;
for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i)
{
if(crypto_connections[i].status > 0) if(crypto_connections[i].status > 0)
{
if(memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) if(memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0)
{
return i; return i;
}
}
}
return -1; return -1;
} }
/* Start a secure connection with other peer who has public_key and ip_port /* Start a secure connection with other peer who has public_key and ip_port
returns -1 if failure returns -1 if failure
returns crypt_connection_id of the initialized connection if everything went well. */ returns crypt_connection_id of the initialized connection if everything went well. */
@ -358,23 +300,17 @@ int crypto_connect(uint8_t * public_key, IP_Port ip_port)
{ {
uint32_t i; uint32_t i;
int id = getcryptconnection_id(public_key); int id = getcryptconnection_id(public_key);
if(id != -1) if(id != -1) {
{
IP_Port c_ip = connection_ip(crypto_connections[id].number); IP_Port c_ip = connection_ip(crypto_connections[id].number);
if(c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port) if(c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port)
{
return -1; return -1;
}
} }
for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i)
{ {
if(crypto_connections[i].status == 0) if(crypto_connections[i].status == 0) {
{
int id = new_connection(ip_port); int id = new_connection(ip_port);
if(id == -1) if(id == -1)
{
return -1; return -1;
}
crypto_connections[i].number = id; crypto_connections[i].number = id;
crypto_connections[i].status = 1; crypto_connections[i].status = 1;
random_nonce(crypto_connections[i].recv_nonce); random_nonce(crypto_connections[i].recv_nonce);
@ -405,20 +341,16 @@ int crypto_inbound(uint8_t * public_key, uint8_t * secret_nonce, uint8_t * sessi
uint32_t i; uint32_t i;
for(i = 0; i < MAX_INCOMING; ++i) for(i = 0; i < MAX_INCOMING; ++i)
{ {
if(incoming_connections[i] != -1) if(incoming_connections[i] != -1) {
{ if(is_connected(incoming_connections[i]) == 4 || is_connected(incoming_connections[i]) == 0) {
if(is_connected(incoming_connections[i]) == 4 || is_connected(incoming_connections[i]) == 0)
{
kill_connection(incoming_connections[i]); kill_connection(incoming_connections[i]);
incoming_connections[i] = -1; incoming_connections[i] = -1;
continue; continue;
} }
if(id_packet(incoming_connections[i]) == 2) if(id_packet(incoming_connections[i]) == 2) {
{
uint8_t temp_data[MAX_DATA_SIZE]; uint8_t temp_data[MAX_DATA_SIZE];
uint16_t len = read_packet(incoming_connections[i], temp_data); uint16_t len = read_packet(incoming_connections[i], temp_data);
if(handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) if(handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) {
{
int connection_id = incoming_connections[i]; int connection_id = incoming_connections[i];
incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */ incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */
return connection_id; return connection_id;
@ -435,11 +367,8 @@ int crypto_inbound(uint8_t * public_key, uint8_t * secret_nonce, uint8_t * sessi
int crypto_kill(int crypt_connection_id) int crypto_kill(int crypt_connection_id)
{ {
if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
{
return 1; return 1;
} if(crypto_connections[crypt_connection_id].status != 0) {
if(crypto_connections[crypt_connection_id].status != 0)
{
crypto_connections[crypt_connection_id].status = 0; crypto_connections[crypt_connection_id].status = 0;
kill_connection(crypto_connections[crypt_connection_id].number); kill_connection(crypto_connections[crypt_connection_id].number);
crypto_connections[crypt_connection_id].number = ~0; crypto_connections[crypt_connection_id].number = ~0;
@ -448,7 +377,6 @@ int crypto_kill(int crypt_connection_id)
return 1; return 1;
} }
/* accept an incoming connection using the parameters provided by crypto_inbound /* accept an incoming connection using the parameters provided by crypto_inbound
return -1 if not successful return -1 if not successful
returns the crypt_connection_id if successful */ returns the crypt_connection_id if successful */
@ -456,9 +384,7 @@ int accept_crypto_inbound(int connection_id, uint8_t * public_key, uint8_t * sec
{ {
uint32_t i; uint32_t i;
if(connection_id == -1) if(connection_id == -1)
{
return -1; return -1;
}
/* /*
if(getcryptconnection_id(public_key) != -1) if(getcryptconnection_id(public_key) != -1)
{ {
@ -466,8 +392,7 @@ int accept_crypto_inbound(int connection_id, uint8_t * public_key, uint8_t * sec
}*/ }*/
for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i)
{ {
if(crypto_connections[i].status == 0) if(crypto_connections[i].status == 0) {
{
crypto_connections[i].number = connection_id; crypto_connections[i].number = connection_id;
crypto_connections[i].status = 2; crypto_connections[i].status = 2;
random_nonce(crypto_connections[i].recv_nonce); random_nonce(crypto_connections[i].recv_nonce);
@ -494,19 +419,16 @@ int accept_crypto_inbound(int connection_id, uint8_t * public_key, uint8_t * sec
return -1; return -1;
} }
/* return 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet /* return 0 if no connection, 1 we have sent a handshake, 2 if connection is not confirmed yet
(we have received a handshake but no empty data packet), 3 if the connection is established. (we have received a handshake but no empty data packet), 3 if the connection is established.
4 if the connection is timed out and waiting to be killed */ 4 if the connection is timed out and waiting to be killed */
int is_cryptoconnected(int crypt_connection_id) int is_cryptoconnected(int crypt_connection_id)
{ {
if(crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS) if(crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS)
{
return crypto_connections[crypt_connection_id].status; return crypto_connections[crypt_connection_id].status;
}
return 0; return 0;
} }
/* Generate our public and private keys /* Generate our public and private keys
Only call this function the first time the program starts. */ Only call this function the first time the program starts. */
void new_keys() void new_keys()
@ -537,10 +459,8 @@ void load_keys(uint8_t * keys)
int new_incoming(int id) int new_incoming(int id)
{ {
uint32_t i; uint32_t i;
for(i = 0; i < MAX_INCOMING; ++i) for(i = 0; i < MAX_INCOMING; ++i) {
{ if(incoming_connections[i] == -1) {
if(incoming_connections[i] == -1)
{
incoming_connections[i] = id; incoming_connections[i] = id;
return 0; return 0;
} }
@ -553,13 +473,10 @@ int new_incoming(int id)
static void handle_incomings() static void handle_incomings()
{ {
int income; int income;
while(1) while(1) {
{
income = incoming_connection(); income = incoming_connection();
if(income == -1 || new_incoming(income) ) if(income == -1 || new_incoming(income) )
{
break; break;
}
} }
} }
@ -578,17 +495,11 @@ static void receive_crypto()
uint16_t len; uint16_t len;
if(id_packet(crypto_connections[i].number) == 1) if(id_packet(crypto_connections[i].number) == 1)
/* if the packet is a friend request drop it (because we are already friends) */ /* if the packet is a friend request drop it (because we are already friends) */
{
len = read_packet(crypto_connections[i].number, temp_data); len = read_packet(crypto_connections[i].number, temp_data);
if(id_packet(crypto_connections[i].number) == 2) { /* handle handshake packet. */
}
if(id_packet(crypto_connections[i].number) == 2) /* handle handshake packet. */
{
len = read_packet(crypto_connections[i].number, temp_data); len = read_packet(crypto_connections[i].number, temp_data);
if(handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) if(handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) {
{ if(memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
if(memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0)
{
memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
increment_nonce(crypto_connections[i].sent_nonce); increment_nonce(crypto_connections[i].sent_nonce);
@ -600,17 +511,14 @@ static void receive_crypto()
} }
} }
else if(id_packet(crypto_connections[i].number) != -1) else if(id_packet(crypto_connections[i].number) != -1)
{
/* This should not happen /* This should not happen
kill the connection if it does */ kill the connection if it does */
crypto_kill(crypto_connections[i].number); crypto_kill(crypto_connections[i].number);
}
} }
if(crypto_connections[i].status == 2) if(crypto_connections[i].status == 2)
{ {
if(id_packet(crypto_connections[i].number) == 3) if(id_packet(crypto_connections[i].number) == 3) {
{
uint8_t temp_data[MAX_DATA_SIZE]; uint8_t temp_data[MAX_DATA_SIZE];
uint8_t data[MAX_DATA_SIZE]; uint8_t data[MAX_DATA_SIZE];
int length = read_packet(crypto_connections[i].number, temp_data); int length = read_packet(crypto_connections[i].number, temp_data);
@ -618,8 +526,7 @@ static void receive_crypto()
crypto_connections[i].sessionsecret_key, crypto_connections[i].sessionsecret_key,
crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data);
uint32_t zero = 0; uint32_t zero = 0;
if(len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) if(len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) {
{
increment_nonce(crypto_connections[i].recv_nonce); increment_nonce(crypto_connections[i].recv_nonce);
crypto_connections[i].status = 3; crypto_connections[i].status = 3;
@ -627,18 +534,14 @@ static void receive_crypto()
kill_connection_in(crypto_connections[i].number, 3000000); kill_connection_in(crypto_connections[i].number, 3000000);
} }
else else
{
/* This should not happen /* This should not happen
kill the connection if it does */ kill the connection if it does */
crypto_kill(crypto_connections[i].number); crypto_kill(crypto_connections[i].number);
}
} }
else if(id_packet(crypto_connections[i].number) != -1) else if(id_packet(crypto_connections[i].number) != -1)
{
/* This should not happen /* This should not happen
kill the connection if it does */ kill the connection if it does */
crypto_kill(crypto_connections[i].number); crypto_kill(crypto_connections[i].number);
}
} }
} }
} }
@ -651,22 +554,16 @@ void initNetCrypto()
memset(incoming_connections, -1 ,sizeof(incoming_connections)); memset(incoming_connections, -1 ,sizeof(incoming_connections));
uint32_t i; uint32_t i;
for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i)
{
crypto_connections[i].number = ~0; crypto_connections[i].number = ~0;
}
} }
static void killTimedout() static void killTimedout()
{ {
uint32_t i; uint32_t i;
for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) for(i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
{
if(crypto_connections[i].status != 0 && is_connected(crypto_connections[i].number) == 4) if(crypto_connections[i].status != 0 && is_connected(crypto_connections[i].number) == 4)
{
crypto_connections[i].status = 4; crypto_connections[i].status = 4;
} else if(is_connected(crypto_connections[i].number) == 4) {
else if(is_connected(crypto_connections[i].number) == 4)
{
kill_connection(crypto_connections[i].number); kill_connection(crypto_connections[i].number);
crypto_connections[i].number = ~0; crypto_connections[i].number = ~0;
} }

View File

@ -1,26 +1,26 @@
/* net_crypto.h /* net_crypto.h
* *
* Functions for the core network crypto. * Functions for the core network crypto.
* *
* Copyright (C) 2013 Tox project All Rights Reserved.
Copyright (C) 2013 Tox project All Rights Reserved. *
* This file is part of Tox.
*
* 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/>.
*
*/
This file is part of Tox.
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/>.
*/
#ifndef NET_CRYPTO_H #ifndef NET_CRYPTO_H
#define NET_CRYPTO_H #define NET_CRYPTO_H
@ -55,13 +55,11 @@ int decrypt_data(uint8_t * public_key, uint8_t * secret_key, uint8_t * nonce,
/* fill the given nonce with random bytes. */ /* fill the given nonce with random bytes. */
void random_nonce(uint8_t * nonce); void random_nonce(uint8_t * nonce);
/* return 0 if there is no received data in the buffer /* return 0 if there is no received data in the buffer
return -1 if the packet was discarded. return -1 if the packet was discarded.
return length of received data if successful */ return length of received data if successful */
int read_cryptpacket(int crypt_connection_id, uint8_t * data); int read_cryptpacket(int crypt_connection_id, uint8_t * data);
/* return 0 if data could not be put in packet queue /* return 0 if data could not be put in packet queue
return 1 if data was put into the queue */ return 1 if data was put into the queue */
int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length); int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length);
@ -74,20 +72,17 @@ int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length);
returns the length of the created packet on success */ returns the length of the created packet on success */
int create_request(uint8_t * packet, uint8_t * public_key, uint8_t * data, uint32_t length, uint8_t request_id); int create_request(uint8_t * packet, uint8_t * public_key, uint8_t * data, uint32_t length, uint8_t request_id);
/* puts the senders public key in the request in public_key, the data from the request /* puts the senders public key in the request in public_key, the data from the request
in data if a friend or ping request was sent to us and returns the length of the data. in data if a friend or ping request was sent to us and returns the length of the data.
packet is the request packet and length is its length packet is the request packet and length is its length
return -1 if not valid request. */ return -1 if not valid request. */
int handle_request(uint8_t * public_key, uint8_t * data, uint8_t * packet, uint16_t length); int handle_request(uint8_t * public_key, uint8_t * data, uint8_t * packet, uint16_t length);
/* Start a secure connection with other peer who has public_key and ip_port /* Start a secure connection with other peer who has public_key and ip_port
returns -1 if failure returns -1 if failure
returns crypt_connection_id of the initialized connection if everything went well. */ returns crypt_connection_id of the initialized connection if everything went well. */
int crypto_connect(uint8_t * public_key, IP_Port ip_port); int crypto_connect(uint8_t * public_key, IP_Port ip_port);
/* kill a crypto connection /* kill a crypto connection
return 0 if killed successfully return 0 if killed successfully
return 1 if there was a problem. */ return 1 if there was a problem. */
@ -102,7 +97,6 @@ int crypto_kill(int crypt_connection_id);
to refuse it just call kill_connection(...) on the connection id */ to refuse it just call kill_connection(...) on the connection id */
int crypto_inbound(uint8_t * public_key, uint8_t * secret_nonce, uint8_t * session_key); int crypto_inbound(uint8_t * public_key, uint8_t * secret_nonce, uint8_t * session_key);
/* accept an incoming connection using the parameters provided by crypto_inbound /* accept an incoming connection using the parameters provided by crypto_inbound
return -1 if not successful return -1 if not successful
returns the crypt_connection_id if successful */ returns the crypt_connection_id if successful */

View File

@ -1,30 +1,28 @@
/* network.h /* network.h
* *
* Functions for the core networking. * Functions for the core networking.
* *
* Copyright (C) 2013 Tox project All Rights Reserved.
Copyright (C) 2013 Tox project All Rights Reserved. *
* This file is part of Tox.
This file is part of Tox. *
* Tox is free software: you can redistribute it and/or modify
Tox is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or
the Free Software Foundation, either version 3 of the License, or * (at your option) any later version.
(at your option) any later version. *
* Tox is distributed in the hope that it will be useful,
Tox is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.
GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License * along with Tox. If not, see <http://www.gnu.org/licenses/>.
along with Tox. If not, see <http://www.gnu.org/licenses/>. *
*/
*/
#include "network.h" #include "network.h"
/* returns current UNIX time in microseconds (us). */ /* returns current UNIX time in microseconds (us). */
uint64_t current_time() uint64_t current_time()
{ {
@ -44,8 +42,6 @@ uint64_t current_time()
time = 1000000UL*a.tv_sec + a.tv_usec; time = 1000000UL*a.tv_sec + a.tv_usec;
return time; return time;
#endif #endif
} }
/* return a random number /* return a random number
@ -69,7 +65,6 @@ int sendpacket(IP_Port ip_port, uint8_t * data, uint32_t length)
{ {
ADDR addr = {AF_INET, ip_port.port, ip_port.ip}; ADDR addr = {AF_INET, ip_port.port, ip_port.ip};
return sendto(sock,(char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); return sendto(sock,(char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr));
} }
/* Function to receive data, ip and port of sender is put into ip_port /* Function to receive data, ip and port of sender is put into ip_port
@ -94,7 +89,6 @@ int receivepacket(IP_Port * ip_port, uint8_t * data, uint32_t * length)
ip_port->ip = addr.ip; ip_port->ip = addr.ip;
ip_port->port = addr.port; ip_port->port = addr.port;
return 0; return 0;
} }
/* initialize networking /* initialize networking
@ -103,32 +97,28 @@ int receivepacket(IP_Port * ip_port, uint8_t * data, uint32_t * length)
port is in host byte order (this means don't worry about it) port is in host byte order (this means don't worry about it)
returns 0 if no problems returns 0 if no problems
returns -1 if there are problems */ returns -1 if there are problems */
int init_networking(IP ip ,uint16_t port) int init_networking(IP ip, uint16_t port)
{ {
#ifdef WIN32 #ifdef WIN32
WSADATA wsaData; WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR)
{
return -1; return -1;
}
#else #else
srandom((uint32_t)current_time()); srandom((uint32_t)current_time());
#endif #endif
srand((uint32_t)current_time()); srand((uint32_t)current_time());
/* initialize our socket */ /* initialize our socket */
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
/* Check for socket error */ /* Check for socket error */
#ifdef WIN32 #ifdef WIN32
if (sock == INVALID_SOCKET) //MSDN recommends this if (sock == INVALID_SOCKET) /* MSDN recommends this */
return -1; return -1;
#else #else
if (sock < 0) if (sock < 0)
return -1; return -1;
#endif #endif
/* Functions to increase the size of the send and receive UDP buffers /* Functions to increase the size of the send and receive UDP buffers
NOTE: uncomment if necessary */ NOTE: uncomment if necessary */
@ -140,10 +130,13 @@ int init_networking(IP ip ,uint16_t port)
} }
if(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&n, sizeof(n)) == -1) if(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&n, sizeof(n)) == -1)
{
return -1; return -1;
}*/ */
/* Enable broadcast on socket */
int broadcast = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast, sizeof(broadcast));
/* Set socket nonblocking */ /* Set socket nonblocking */
#ifdef WIN32 #ifdef WIN32
/* I think this works for windows */ /* I think this works for windows */
@ -190,11 +183,9 @@ int resolve_addr(char *address)
int success = getaddrinfo(address, "7", &hints, &server); int success = getaddrinfo(address, "7", &hints, &server);
if(success != 0) if(success != 0)
{
return -1; return -1;
}
int resolved = ((struct sockaddr_in*)server->ai_addr)->sin_addr.s_addr; int resolved = ((struct sockaddr_in*)server->ai_addr)->sin_addr.s_addr;
freeaddrinfo(server); freeaddrinfo(server);
return resolved; return resolved;
} }

View File

@ -1,27 +1,25 @@
/* network.h /* network.h
* *
* Datatypes, functions and includes for the core networking. * Datatypes, functions and includes for the core networking.
* *
* Copyright (C) 2013 Tox project All Rights Reserved.
Copyright (C) 2013 Tox project All Rights Reserved. *
* This file is part of Tox.
This file is part of Tox. *
* Tox is free software: you can redistribute it and/or modify
Tox is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or
the Free Software Foundation, either version 3 of the License, or * (at your option) any later version.
(at your option) any later version. *
* Tox is distributed in the hope that it will be useful,
Tox is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.
GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License * along with Tox. If not, see <http://www.gnu.org/licenses/>.
along with Tox. If not, see <http://www.gnu.org/licenses/>. *
*/
*/
#ifndef NETWORK_H #ifndef NETWORK_H
#define NETWORK_H #define NETWORK_H
@ -32,8 +30,6 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#ifdef WIN32 /* Put win32 includes here */ #ifdef WIN32 /* Put win32 includes here */
//Windows XP //Windows XP
#define WINVER 0x0501 #define WINVER 0x0501
@ -99,7 +95,6 @@ typedef struct
#endif #endif
}ADDR; }ADDR;
/* returns current time in milleseconds since the epoch. */ /* returns current time in milleseconds since the epoch. */
uint64_t current_time(); uint64_t current_time();

View File

@ -6,6 +6,25 @@
* gcc -O2 -Wall -D VANILLA_NACL -o bootstrap_server ../core/Lossless_UDP.c ../core/network.c ../core/net_crypto.c ../core/Messenger.c ../core/DHT.c ../core/friend_requests.c ../nacl/build/${HOSTNAME%.*}/lib/amd64/{cpucycles.o,libnacl.a,randombytes.o} DHT_bootstrap.c * gcc -O2 -Wall -D VANILLA_NACL -o bootstrap_server ../core/Lossless_UDP.c ../core/network.c ../core/net_crypto.c ../core/Messenger.c ../core/DHT.c ../core/friend_requests.c ../nacl/build/${HOSTNAME%.*}/lib/amd64/{cpucycles.o,libnacl.a,randombytes.o} DHT_bootstrap.c
* *
* gcc -O2 -Wall -o bootstrap_server ../core/Lossless_UDP.c ../core/network.c ../core/net_crypto.c ../core/Messenger.c ../core/DHT.c ../core/friend_requests.c -lsodium DHT_bootstrap.c * gcc -O2 -Wall -o bootstrap_server ../core/Lossless_UDP.c ../core/network.c ../core/net_crypto.c ../core/Messenger.c ../core/DHT.c ../core/friend_requests.c -lsodium DHT_bootstrap.c
*
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/ */
#include "../core/DHT.h" #include "../core/DHT.h"
@ -22,12 +41,14 @@
#define PORT 33445 #define PORT 33445
//TODO: rewrite
unsigned char * hex_string_to_bin(char hex_string[]) unsigned char * hex_string_to_bin(char hex_string[])
{ {
unsigned char * val = malloc(strlen(hex_string)); size_t len = strlen(hex_string);
unsigned char * val = malloc(len);
char * pos = hex_string; char * pos = hex_string;
int i=0; int i=0;
while(i < strlen(hex_string)) while(i < len)
{ {
sscanf(pos,"%2hhx",&val[i]); sscanf(pos,"%2hhx",&val[i]);
pos+=2; pos+=2;
@ -120,4 +141,4 @@ int main(int argc, char *argv[])
} }
shutdown_networking(); shutdown_networking();
return 0; return 0;
} }

View File

@ -6,4 +6,5 @@ set(exe_name DHT_bootstrap_daemon)
add_executable(${exe_name} add_executable(${exe_name}
DHT_bootstrap_daemon.c) DHT_bootstrap_daemon.c)
target_link_libraries(${exe_name} config)
linkCoreLibraries(${exe_name}) linkCoreLibraries(${exe_name})

View File

@ -1,50 +1,323 @@
/* DHT boostrap /* DHT boostrap
* *
* A simple DHT boostrap server for tox (daemon edition) * A simple DHT boostrap server for tox - daemon edition.
*/ *
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/
#include <sys/types.h> /* pid_t */ #include <sys/types.h> /* pid_t */
#include <sys/stat.h> /* umask */ #include <sys/stat.h> /* umask */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* POSIX things */ #include <unistd.h> /* POSIX things */
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <libconfig.h>
#include <arpa/inet.h> /* htons() */
#include <string.h> /* strcpy() */
#include "../../core/DHT.h" #include "../../core/DHT.h"
#include "../../core/friend_requests.h" #include "../../core/friend_requests.h"
#define DEFAULT_PORT 33445
/* Sleep function (x = milliseconds) */ #define DEFAULT_PID_FILE "bootstrap_server.pid"
#ifdef WIN32 #define DEFAULT_KEYS_FILE "bootstrap_server.keys"
#define c_sleep(x) Sleep(1*x)
#else /* Server info struct */
#include <unistd.h> struct server_info_s {
#define c_sleep(x) usleep(1000*x) int valid;
#endif IP_Port conn;
uint8_t bs_pk[32];
#define PORT 33445 };
#define USERNAME getenv("USER")
#define PIDFILE "/home/%s/.bootstrap_server.pid" /* %s represents the unser's name */ /* This is the struct configure_server() uses to return its data to */
struct server_conf_s {
int err;
int port;
char pid_file[512];
char keys_file[512];
struct server_info_s info[32];
};
int b16_to_key(char b16_string[], uint8_t *bs_pubkey) {
int i;
unsigned int num1 = 0, num2 = 0;
for(i = 0; i < 32; ++i)
{
sscanf(&b16_string[i*2], "%1X", &num1);
sscanf(&b16_string[i*2+1], "%1X", &num2);
num1 = num1 << 4;
bs_pubkey[i] = bs_pubkey[i] | num1;
bs_pubkey[i] = bs_pubkey[i] | num2;
}
return 0;
}
/* This unction connects to all specified servers
and connect to them.
returns 1 if the connection to the DHT is up
returns -1 if all attempts failed
*/
int connect_to_servers(struct server_info_s *info)
{
int i;
int c;
IP_Port ip_port;
uint8_t data[MAX_UDP_PACKET_SIZE];
uint32_t length;
for(i = 0; i < 32; ++i) {
if(info[i].valid) {
/* Actual bootstrapping code goes here */
//puts("Calling DHT_bootstrap");
DHT_bootstrap(info[i].conn, info[i].bs_pk);
}
}
/* Check if we're connected to the DHT */
for(c = 0; c != 100; ++c) {
usleep(10000);
if(DHT_isconnected()) {
//puts("Connected");
return 1;
break;
}
if(DHT_isconnected() == 0 && c == 99) {
//puts("Not connected");
return -1;
break;
}
doDHT();
while(receivepacket(&ip_port, data, &length) != -1)
{
DHT_handlepacket(data, length, ip_port);
}
}
/* This probably never happens */
return 0;
}
void manage_keys(char *keys_file)
{
const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
uint8_t keys[KEYS_SIZE];
/* TODO: stat the file before trying to open it. We aren't cave people! */
FILE *keysf = fopen(keys_file, "r");
if (keysf != NULL) {
/* if file was opened successfully -- load keys */
size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keysf);
if (read_size != KEYS_SIZE) {
printf("Error while reading the key file\nExiting.\n");
exit(1);
} else {
printf("Keys loaded successfully\n");
}
load_keys(keys);
} else {
/* otherwise save new keys */
/* Silly work-around to ignore any errors coming from new_keys() */
new_keys();
save_keys(keys);
keysf = fopen(keys_file, "w");
if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keysf) != KEYS_SIZE) {
printf("Error while writing the key file.\nExiting.\n");
exit(1);
} else {
printf("Keys saved successfully\n");
}
}
fclose(keysf);
}
/* This reads the configuration file, and returns a struct server_conf_s with:
*an error number:
*-1 = file wasn't read, for whatever reason
*-2 = no bootstrap servers found
*the port
*the location of the keys file
*the location of the PID file
*the list of bootstrap servers
*/
struct server_conf_s configure_server(char *cfg_file)
{
config_t cfg;
config_setting_t *server_list;
/* This one will be strcpy'd into the pid_file array in server_conf */
const char *pid_file_tmp;
const char *keys_file_tmp;
/* Remote bootstrap server variables */
int bs_port;
const char *bs_ip;
const char *bs_pk;
/* The big struct */
static struct server_conf_s server_conf;
/* Set both to their default values. If there's an error
with opening/reading the config file, we return right away */
server_conf.port = DEFAULT_PORT;
strcpy(server_conf.pid_file, DEFAULT_PID_FILE);
strcpy(server_conf.keys_file, DEFAULT_KEYS_FILE);
config_init(&cfg);
/* Read the file. If there is an error, report it and exit. */
if(! config_read_file(&cfg, cfg_file))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg);
server_conf.err = -1;
return server_conf;
}
/* Get the port to listen on */
if(config_lookup_int(&cfg, "port", &server_conf.port)) {
//printf("Port: %d\n", port);
} else {
fprintf(stderr, "No 'port' setting in configuration file.\n");
}
/* Get PID file location */
if(config_lookup_string(&cfg, "pid_file", &pid_file_tmp)) {
//printf("PID file: %s\n", pid_file_tmp);
strcpy(server_conf.pid_file, pid_file_tmp);
} else {
fprintf(stderr, "No 'pid_file' setting in configuration file.\n");
}
/* Get keys file location */
if(config_lookup_string(&cfg, "keys_file", &keys_file_tmp)) {
//printf("Keys file: %s\n", keys_file_tmp);
strcpy(server_conf.keys_file, keys_file_tmp);
} else {
fprintf(stderr, "No 'keys_file' setting in configuration file.\n");
}
/* Get all the servers in the list */
server_list = config_lookup(&cfg, "bootstrap_servers");
if(server_list != NULL) {
int count = config_setting_length(server_list);
int i;
char tmp_ip[30]; /* IP */
char tmp_pk[64]; /* bs_pk */
for(i = 0; i < count; ++i) {
config_setting_t *server = config_setting_get_elem(server_list, i);
/* Get a pointer on the key aray */
uint8_t *bs_pk_p = server_conf.info[i].bs_pk;
/* Only output the record if all of the expected fields are present. */
if(!(config_setting_lookup_string(server, "ip", &bs_ip)
&& config_setting_lookup_int(server, "port", &bs_port)
&& config_setting_lookup_string(server, "bs_pk", &bs_pk)))
continue;
/* Converting all that stuff into usable formats and storing
it away in the server_info struct */
server_conf.info[i].valid = 1;
if(resolve_addr(strcpy(tmp_ip, bs_ip)) == -1) {
server_conf.info[i].valid = 0;
printf("bootstrap_server %d: Invalid IP\n", i);
}
if(strlen(bs_pk) != 64) {
server_conf.info[i].valid = 0;
printf("bootstrap_server %d: Invalid public key\n", i);
}
if(!bs_port) {
server_conf.info[i].valid = 0;
printf("bootstrap_server %d: Invalid port\n", i);
}
server_conf.info[i].conn.ip.i = resolve_addr(strcpy(tmp_ip, bs_ip));
server_conf.info[i].conn.port = htons(bs_port);
b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p);
}
/* Check if at least one server entry is valid */
for(i = 0; i < 32; ++i) {
if(server_conf.info[i].valid)
break;
else
server_conf.err = -2;
}
} else {
server_conf.err = -2;
}
config_destroy(&cfg);
return server_conf;
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
char pidfloc[512]; /* Location of the soon-to-be PID file */
pid_t pid, sid; /* Process- and Session-ID */ pid_t pid, sid; /* Process- and Session-ID */
struct server_conf_s server_conf;
FILE *pidf; /* The PID file */ FILE *pidf; /* The PID file */
/* Assemble PID file location an try to open the file */ if(argc < 2) {
sprintf(pidfloc, PIDFILE, USERNAME); printf("Please specify a configuration file.\n");
pidf = fopen(pidfloc, "w"); exit(EXIT_FAILURE);
}
/* Generate new keypair */
new_keys(); /* Read the config file */
server_conf = configure_server(argv[1]);
printf("PID file: %s\n", server_conf.pid_file);
printf("Key file: %s\n", server_conf.keys_file);
if(server_conf.err == -1)
printf("Config file not read.\n");
if(server_conf.err == -2)
printf("No valid servers in list.\n");
/* Open PID file for writing - if an error happens,
it will be caught down the line */
pidf = fopen(server_conf.pid_file, "w");
/* Manage the keys */
/* for now, just ignore any errors after this call. */
int tmperr = errno;
manage_keys(server_conf.keys_file);
errno = tmperr;
/* Public key */ /* Public key */
uint32_t i; int i;
printf("\nPublic Key: "); printf("\nPublic Key: ");
for(i = 0; i < 32; i++) for(i = 0; i < 32; ++i)
{ {
uint8_t ln, hn; uint8_t ln, hn;
ln = 0x0F & self_public_key[i]; ln = 0x0F & self_public_key[i];
@ -53,84 +326,95 @@ int main(int argc, char *argv[]) {
printf("%X%X", hn, ln); printf("%X%X", hn, ln);
} }
printf("\n"); printf("\n");
/* initialize networking /* initialize networking
bind to ip 0.0.0.0:PORT */ bind to ip 0.0.0.0:PORT */
IP ip; IP ip;
ip.i = 0; ip.i = 0;
init_networking(ip, PORT); init_networking(ip, server_conf.port);
/* Bootstrap the DHT
This one throws odd errors, too. Ignore. I assume they come
from somewhere in the core. */
tmperr = errno;
connect_to_servers(server_conf.info);
errno = tmperr;
if(!DHT_isconnected()) {
puts("Could not establish DHT connection. Check server settings.\n");
exit(EXIT_FAILURE);
} else {
printf("Connected to DHT successfully.\n");
}
/* If there's been an error, exit before forking off */ /* If there's been an error, exit before forking off */
if (errno != 0) { if (errno != 0) {
perror("Error"); perror("Error");
printf("Error(s) occured during start-up. Exiting.\n"); printf("Error(s) occured during start-up. Exiting.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// /* Assemble the location of the PID file */ /* Things that make the daemon work come past here.
// sprintf(pidfloc, PIDFILE, USERNAME); There should be nothing here but the daemon code and
// pidf = fopen(pidfloc, "w"); the main loop. */
// /* Check if we can actually open the file */
// if(pidf == NULL) { /* Fork off from the parent process */
// printf("Couldn't open PID-File %s for writing.\n", pidfloc);
// exit(EXIT_FAILURE);
// }
/* Fork off the parent process */
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
printf("Forking failed.\n"); printf("Forking failed.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* If we got a good PID, then /* If we got a good PID, then
we can exit the parent process. */ we can exit the parent process. */
if (pid > 0) { if (pid > 0) {
printf("Forked successfully: %d\n", pid); printf("Forked successfully: %d\n", pid);
/* Write the PID file */ /* Write the PID file */
fprintf(pidf, "%d\n", pid); fprintf(pidf, "%d\n", pid);
fclose(pidf); fclose(pidf);
/* Exit parent */ /* Exit parent */
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
/* Change the file mode mask */ /* Change the file mode mask */
umask(0); umask(0);
/* Create a new SID for the child process */ /* Create a new SID for the child process */
sid = setsid(); sid = setsid();
if (sid < 0) { if (sid < 0) {
printf("SID creation failure.\n"); printf("SID creation failure.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* Change the current working directory */ /* Change the current working directory */
if ((chdir("/")) < 0) { if ((chdir("/")) < 0) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* Go quiet */ /* Go quiet */
close(STDIN_FILENO);
close(STDOUT_FILENO); close(STDOUT_FILENO);
close(STDIN_FILENO);
close(STDERR_FILENO); close(STDERR_FILENO);
/* Main loop */
IP_Port ip_port; IP_Port ip_port;
uint8_t data[MAX_UDP_PACKET_SIZE]; uint8_t data[MAX_UDP_PACKET_SIZE];
uint32_t length; uint32_t length;
/* Main loop */ while(1)
while(1) { {
doDHT(); doDHT();
while(receivepacket(&ip_port, data, &length) != -1) {
while(receivepacket(&ip_port, data, &length) != -1)
{
DHT_handlepacket(data, length, ip_port); DHT_handlepacket(data, length, ip_port);
friendreq_handlepacket(data, length, ip_port); friendreq_handlepacket(data, length, ip_port);
} }
c_sleep(1); usleep(10000);
} }
shutdown_networking(); shutdown_networking();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }

View File

@ -0,0 +1,109 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: DHT_bootstrap_daemon
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start the Tox bootstrapping server
# Description: Use this piece of junk to start the Tox
# bootstrap server.
### END INIT INFO
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="ProjectTox bootstrap server daemon"
NAME=DHT_bootstrap_daemon
CFG=/home/$USER/server.cfg
DAEMON=/home/$USER/$NAME
DAEMON_ARGS="$CFG"
PIDFILE=/home/$USER/.$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Read configuration variable file if it is present
#[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
#
# Function that starts the daemon/service
#
do_start()
{
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
sleep 1
}
#
# Function that stops the daemon/service
#
do_stop()
{
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --exec $DAEMON
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
restart) #|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
exit 3
;;
esac

View File

@ -1,109 +0,0 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: bootstrap_server
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start the Tox bootstrapping server
# Description: Use this piece of junk to start the Tox
# bootstrap server.
### END INIT INFO
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="ProjectTox bootstrap server daemon"
NAME=bootstrap_server
DAEMON=/home/$USER/$NAME
DAEMON_ARGS=""
PIDFILE=/home/$USER/.$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
#
# Function that starts the daemon/service
#
do_start()
{
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
sleep 1
}
#
# Function that stops the daemon/service
#
do_stop()
{
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --exec $DAEMON
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
restart) #|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
exit 3
;;
esac

View File

@ -0,0 +1,30 @@
// ProjectTox bootstrap server configuration file
// The port used by bootstrap_server to listen on
port = 33445;
// The key file
// make sure that the user who runs the server
// does have permissions to read it/write to it
keys_file = "/home/tom/.bootstrap_server.keys"
// The PID file written to by bootstrap_server,
// make sure that the user who runs the server
// does have permissions to write to it
pid_file = "/home/tom/.bootstrap_server.pid";
// The info of the node bootstap_server will
// bootstrap itself from.
bootstrap_servers = (
{ // Server 1
ip = "198.46.136.167";
port = 33445;
bs_pk = "728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854";
// }
},
{ // Server 2
ip = "192.81.133.111";
port = 33445;
bs_pk = "8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858";
}
);

View File

@ -15,14 +15,33 @@
* Saves all received data to: received.txt * Saves all received data to: received.txt
* *
* EX: ./test 127.0.0.1 33445 filename.txt * EX: ./test 127.0.0.1 33445 filename.txt
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/ */
#include "../core/network.h" #include "../core/network.h"
#include "../core/DHT.h" #include "../core/DHT.h"
#include "../core/net_crypto.h" #include "../core/net_crypto.h"
#include <string.h> #include <string.h>
//Sleep function (x = milliseconds) /* Sleep function (x = milliseconds) */
#ifdef WIN32 #ifdef WIN32
#define c_sleep(x) Sleep(1*x) #define c_sleep(x) Sleep(1*x)
@ -41,15 +60,14 @@ void printip(IP_Port ip_port)
printf("\nIP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port)); printf("\nIP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port));
} }
//TODO: rewrite
//horrible function from one of my first C programs.
//only here because I was too lazy to write a proper one.
unsigned char * hex_string_to_bin(char hex_string[]) unsigned char * hex_string_to_bin(char hex_string[])
{ {
unsigned char * val = malloc(strlen(hex_string)); size_t len = strlen(hex_string);
unsigned char * val = malloc(len);
char * pos = hex_string; char * pos = hex_string;
int i=0; int i=0;
while(i < strlen(hex_string)) while(i < len)
{ {
sscanf(pos,"%2hhx",&val[i]); sscanf(pos,"%2hhx",&val[i]);
pos+=2; pos+=2;
@ -69,8 +87,7 @@ int main(int argc, char *argv[])
new_keys(); new_keys();
printf("OUR ID: "); printf("OUR ID: ");
uint32_t i; uint32_t i;
for(i = 0; i < 32; i++) for(i = 0; i < 32; i++) {
{
if(self_public_key[i] < 16) if(self_public_key[i] < 16)
printf("0"); printf("0");
printf("%hhX",self_public_key[i]); printf("%hhX",self_public_key[i]);
@ -86,8 +103,7 @@ int main(int argc, char *argv[])
uint8_t friend_id[32]; uint8_t friend_id[32];
memcpy(friend_id, hex_string_to_bin(temp_id), 32); memcpy(friend_id, hex_string_to_bin(temp_id), 32);
/* memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); */
//memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32);
DHT_addfriend(friend_id); DHT_addfriend(friend_id);
@ -99,15 +115,13 @@ int main(int argc, char *argv[])
int friendrequest = -1; int friendrequest = -1;
uint8_t request_data[512]; uint8_t request_data[512];
//initialize networking /* initialize networking
//bind to ip 0.0.0.0:PORT * bind to ip 0.0.0.0:PORT */
IP ip; IP ip;
ip.i = 0; ip.i = 0;
init_networking(ip, PORT); init_networking(ip, PORT);
initNetCrypto(); initNetCrypto();
perror("Initialization"); perror("Initialization");
IP_Port bootstrap_ip_port; IP_Port bootstrap_ip_port;
bootstrap_ip_port.port = htons(atoi(argv[2])); bootstrap_ip_port.port = htons(atoi(argv[2]));
@ -128,125 +142,102 @@ int main(int argc, char *argv[])
if ( file2==NULL ){return 1;} if ( file2==NULL ){return 1;}
read1 = fread(buffer1, 1, 128, file1); read1 = fread(buffer1, 1, 128, file1);
while(1) while(1) {
{ while(receivepacket(&ip_port, data, &length) != -1) {
if(rand() % 3 != 1) { /* simulate packet loss */
while(receivepacket(&ip_port, data, &length) != -1) if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port)) {
{ /* if packet is not recognized */
if(rand() % 3 != 1)//simulate packet loss
{
if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port))
{
//if packet is not recognized
printf("Received unhandled packet with length: %u\n", length); printf("Received unhandled packet with length: %u\n", length);
} } else {
else
{
printf("Received handled packet with length: %u\n", length); printf("Received handled packet with length: %u\n", length);
} }
} }
} }
friend_ip = DHT_getfriendip(friend_id); friend_ip = DHT_getfriendip(friend_id);
if(friend_ip.ip.i != 0) if(friend_ip.ip.i != 0) {
{ if(connection == -1 && friendrequest == -1) {
if(connection == -1 && friendrequest == -1)
{
printf("Sending friend request to peer:"); printf("Sending friend request to peer:");
printip(friend_ip); printip(friend_ip);
friendrequest = send_friendrequest(friend_id, friend_ip,(uint8_t *) "Hello World", 12); friendrequest = send_friendrequest(friend_id, friend_ip,(uint8_t *) "Hello World", 12);
//connection = crypto_connect((uint8_t *)friend_id, friend_ip); /* connection = crypto_connect((uint8_t *)friend_id, friend_ip); */
//connection = new_connection(friend_ip); /* connection = new_connection(friend_ip); */
} }
if(check_friendrequest(friendrequest) == 1) if(check_friendrequest(friendrequest) == 1) {
{
printf("Started connecting to friend:"); printf("Started connecting to friend:");
connection = crypto_connect(friend_id, friend_ip); connection = crypto_connect(friend_id, friend_ip);
} }
} }
if(inconnection == -1) if(inconnection == -1) {
{
uint8_t secret_nonce[crypto_box_NONCEBYTES]; uint8_t secret_nonce[crypto_box_NONCEBYTES];
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t public_key[crypto_box_PUBLICKEYBYTES];
uint8_t session_key[crypto_box_PUBLICKEYBYTES]; uint8_t session_key[crypto_box_PUBLICKEYBYTES];
inconnection = crypto_inbound(public_key, secret_nonce, session_key); inconnection = crypto_inbound(public_key, secret_nonce, session_key);
inconnection = accept_crypto_inbound(inconnection, acceptedfriend_public_key, secret_nonce, session_key); inconnection = accept_crypto_inbound(inconnection, acceptedfriend_public_key, secret_nonce, session_key);
//inconnection = incoming_connection(); /* inconnection = incoming_connection(); */
if(inconnection != -1) if(inconnection != -1) {
{
printf("Someone connected to us:\n"); printf("Someone connected to us:\n");
// printip(connection_ip(inconnection)); /* printip(connection_ip(inconnection)); */
} }
} }
if(handle_friendrequest(acceptedfriend_public_key, request_data) > 1) if(handle_friendrequest(acceptedfriend_public_key, request_data) > 1) {
{
printf("RECIEVED FRIEND REQUEST: %s\n", request_data); printf("RECIEVED FRIEND REQUEST: %s\n", request_data);
} }
//if someone connected to us write what he sends to a file /* if someone connected to us write what he sends to a file
//also send him our file. * also send him our file. */
if(inconnection != -1) if(inconnection != -1) {
{ if(write_cryptpacket(inconnection, buffer1, read1)) {
if(write_cryptpacket(inconnection, buffer1, read1))
{
printf("Wrote data1.\n"); printf("Wrote data1.\n");
read1 = fread(buffer1, 1, 128, file1); read1 = fread(buffer1, 1, 128, file1);
} }
read2 = read_cryptpacket(inconnection, buffer2); read2 = read_cryptpacket(inconnection, buffer2);
if(read2 != 0) if(read2 != 0) {
{
printf("Received data1.\n"); printf("Received data1.\n");
if(!fwrite(buffer2, read2, 1, file2)) if(!fwrite(buffer2, read2, 1, file2)) {
{
printf("file write error1\n"); printf("file write error1\n");
} }
if(read2 < 128) if(read2 < 128) {
{
printf("Closed file1 %u\n", read2); printf("Closed file1 %u\n", read2);
fclose(file2); fclose(file2);
} }
} }
else if(is_cryptoconnected(inconnection) == 4)//if buffer is empty and the connection timed out. /* if buffer is empty and the connection timed out. */
{ else if(is_cryptoconnected(inconnection) == 4) {
crypto_kill(inconnection); crypto_kill(inconnection);
} }
} }
//if we are connected to a friend send him data from the file. /* if we are connected to a friend send him data from the file.
//also put what he sends us in a file. * also put what he sends us in a file. */
if(is_cryptoconnected(connection) >= 3) if(is_cryptoconnected(connection) >= 3) {
{ if(write_cryptpacket(0, buffer1, read1)) {
if(write_cryptpacket(0, buffer1, read1))
{
printf("Wrote data2.\n"); printf("Wrote data2.\n");
read1 = fread(buffer1, 1, 128, file1); read1 = fread(buffer1, 1, 128, file1);
} }
read2 = read_cryptpacket(0, buffer2); read2 = read_cryptpacket(0, buffer2);
if(read2 != 0) if(read2 != 0) {
{
printf("Received data2.\n"); printf("Received data2.\n");
if(!fwrite(buffer2, read2, 1, file2)) if(!fwrite(buffer2, read2, 1, file2)) {
{
printf("file write error2\n"); printf("file write error2\n");
} }
if(read2 < 128) if(read2 < 128) {
{
printf("Closed file2 %u\n", read2); printf("Closed file2 %u\n", read2);
fclose(file2); fclose(file2);
} }
} }
else if(is_cryptoconnected(connection) == 4)//if buffer is empty and the connection timed out. /* if buffer is empty and the connection timed out. */
{ else if(is_cryptoconnected(connection) == 4) {
crypto_kill(connection); crypto_kill(connection);
} }
} }
doDHT(); doDHT();
doLossless_UDP(); doLossless_UDP();
doNetCrypto(); doNetCrypto();
//print_clientlist(); /*print_clientlist();
//print_friendlist(); *print_friendlist();
//c_sleep(300); *c_sleep(300); */
c_sleep(1); c_sleep(1);
} }
shutdown_networking(); shutdown_networking();
return 0; return 0;
} }

View File

@ -14,7 +14,26 @@
* Saves all received data to: received.txt * Saves all received data to: received.txt
* *
* EX: ./test 127.0.0.1 33445 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef filename.txt ABCDEFGHIJKLMNOPQRSTUVWXYZabcdeg * EX: ./test 127.0.0.1 33445 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef filename.txt ABCDEFGHIJKLMNOPQRSTUVWXYZabcdeg
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/ */
#include "../core/network.h" #include "../core/network.h"
#include "../core/DHT.h" #include "../core/DHT.h"
#include "../core/Lossless_UDP.h" #include "../core/Lossless_UDP.h"
@ -82,68 +101,53 @@ int main(int argc, char *argv[])
if ( file2==NULL ){return 1;} if ( file2==NULL ){return 1;}
read1 = fread(buffer1, 1, 128, file1); read1 = fread(buffer1, 1, 128, file1);
while(1) while(1) {
{
while(receivepacket(&ip_port, data, &length) != -1) while(receivepacket(&ip_port, data, &length) != -1) {
{ if(rand() % 3 != 1) { /* simulate packet loss */
if(rand() % 3 != 1)//simulate packet loss if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port)) {
{ /* if packet is not recognized */
if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port))
{
//if packet is not recognized
printf("Received unhandled packet with length: %u\n", length); printf("Received unhandled packet with length: %u\n", length);
} } else {
else
{
printf("Received handled packet with length: %u\n", length); printf("Received handled packet with length: %u\n", length);
} }
} }
} }
friend_ip = DHT_getfriendip((uint8_t *)argv[3]); friend_ip = DHT_getfriendip((uint8_t *)argv[3]);
if(friend_ip.ip.i != 0) if(friend_ip.ip.i != 0) {
{ if(connection == -1) {
if(connection == -1)
{
printf("Started connecting to friend:"); printf("Started connecting to friend:");
printip(friend_ip); printip(friend_ip);
connection = new_connection(friend_ip); connection = new_connection(friend_ip);
} }
} }
if(inconnection == -1) if(inconnection == -1) {
{
inconnection = incoming_connection(); inconnection = incoming_connection();
if(inconnection != -1) if(inconnection != -1) {
{
printf("Someone connected to us:"); printf("Someone connected to us:");
printip(connection_ip(inconnection)); printip(connection_ip(inconnection));
} }
} }
//if someone connected to us write what he sends to a file /* if someone connected to us write what he sends to a file */
//also send him our file. /* also send him our file. */
if(inconnection != -1) if(inconnection != -1) {
{ if(write_packet(inconnection, buffer1, read1)) {
if(write_packet(inconnection, buffer1, read1))
{
printf("Wrote data.\n"); printf("Wrote data.\n");
read1 = fread(buffer1, 1, 128, file1); read1 = fread(buffer1, 1, 128, file1);
} }
read2 = read_packet(inconnection, buffer2); read2 = read_packet(inconnection, buffer2);
if(read2 != 0) if(read2 != 0) {
{
printf("Received data.\n"); printf("Received data.\n");
if(!fwrite(buffer2, read2, 1, file2)) if(!fwrite(buffer2, read2, 1, file2)) {
{
printf("file write error\n"); printf("file write error\n");
} }
if(read2 < 128) if(read2 < 128) {
{
fclose(file2); fclose(file2);
} }
} }
} }
//if we are connected to a friend send him data from the file. /* if we are connected to a friend send him data from the file.
//also put what he sends us in a file. * also put what he sends us in a file. */
if(is_connected(connection) == 3) if(is_connected(connection) == 3)
{ {
if(write_packet(0, buffer1, read1)) if(write_packet(0, buffer1, read1))
@ -167,9 +171,9 @@ int main(int argc, char *argv[])
} }
doDHT(); doDHT();
doLossless_UDP(); doLossless_UDP();
//print_clientlist(); /* print_clientlist();
//print_friendlist(); * print_friendlist();
//c_sleep(300); * c_sleep(300); */
c_sleep(1); c_sleep(1);
} }

View File

@ -7,7 +7,26 @@
* EX: ./test 127.0.0.1 33445 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * EX: ./test 127.0.0.1 33445 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
* *
* The test will then ask you for the id (in hex format) of the friend you wish to add * The test will then ask you for the id (in hex format) of the friend you wish to add
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/ */
//#include "../core/network.h" //#include "../core/network.h"
#include "../core/DHT.c" #include "../core/DHT.c"
#include "../core/friend_requests.c" #include "../core/friend_requests.c"
@ -28,17 +47,14 @@
#define PORT 33445 #define PORT 33445
void print_clientlist() void print_clientlist()
{ {
uint32_t i, j; uint32_t i, j;
IP_Port p_ip; IP_Port p_ip;
printf("___________________CLOSE________________________________\n"); printf("___________________CLOSE________________________________\n");
for(i = 0; i < 4; i++) for(i = 0; i < 4; i++) {
{
printf("ClientID: "); printf("ClientID: ");
for(j = 0; j < 32; j++) for(j = 0; j < 32; j++) {
{
printf("%c", close_clientlist[i].client_id[j]); printf("%c", close_clientlist[i].client_id[j]);
} }
p_ip = close_clientlist[i].ip_port; p_ip = close_clientlist[i].ip_port;
@ -56,12 +72,10 @@ void print_friendlist()
uint32_t i, j, k; uint32_t i, j, k;
IP_Port p_ip; IP_Port p_ip;
printf("_________________FRIENDS__________________________________\n"); printf("_________________FRIENDS__________________________________\n");
for(k = 0; k < num_friends; k++) for(k = 0; k < num_friends; k++) {
{
printf("FRIEND %u\n", k); printf("FRIEND %u\n", k);
printf("ID: "); printf("ID: ");
for(j = 0; j < 32; j++) for(j = 0; j < 32; j++) {
{
printf("%c", friends_list[k].client_id[j]); printf("%c", friends_list[k].client_id[j]);
} }
p_ip = DHT_getfriendip(friends_list[k].client_id); p_ip = DHT_getfriendip(friends_list[k].client_id);
@ -69,11 +83,9 @@ void print_friendlist()
printf("\nCLIENTS IN LIST:\n\n"); printf("\nCLIENTS IN LIST:\n\n");
for(i = 0; i < 4; i++) for(i = 0; i < 4; i++) {
{
printf("ClientID: "); printf("ClientID: ");
for(j = 0; j < 32; j++) for(j = 0; j < 32; j++) {
{
if(0 <= friends_list[k].client_list[i].client_id[j] && friends_list[k].client_list[i].client_id[j] < 16) if(0 <= friends_list[k].client_list[i].client_id[j] && friends_list[k].client_list[i].client_id[j] < 16)
printf("0"); printf("0");
printf("%hhX", friends_list[k].client_list[i].client_id[j]); printf("%hhX", friends_list[k].client_list[i].client_id[j]);
@ -94,8 +106,7 @@ void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port)
uint32_t i; uint32_t i;
printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length);
printf("--------------------BEGIN-----------------------------\n"); printf("--------------------BEGIN-----------------------------\n");
for(i = 0; i < length; i++) for(i = 0; i < length; i++) {
{
if(data[i] < 16) if(data[i] < 16)
printf("0"); printf("0");
printf("%hhX",data[i]); printf("%hhX",data[i]);
@ -103,14 +114,14 @@ void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port)
printf("\n--------------------END-----------------------------\n\n\n"); printf("\n--------------------END-----------------------------\n\n\n");
} }
//horrible function from one of my first C programs. //TODO: rewrite
//only here because I was too lazy to write a proper one.
unsigned char * hex_string_to_bin(char hex_string[]) unsigned char * hex_string_to_bin(char hex_string[])
{ {
unsigned char * val = malloc(strlen(hex_string)); size_t len = strlen(hex_string);
unsigned char * val = malloc(len);
char * pos = hex_string; char * pos = hex_string;
int i=0; int i=0;
while(i < strlen(hex_string)) while(i < len)
{ {
sscanf(pos,"%2hhx",&val[i]); sscanf(pos,"%2hhx",&val[i]);
pos+=2; pos+=2;
@ -130,8 +141,7 @@ int main(int argc, char *argv[])
new_keys(); new_keys();
printf("OUR ID: "); printf("OUR ID: ");
uint32_t i; uint32_t i;
for(i = 0; i < 32; i++) for(i = 0; i < 32; i++) {
{
if(self_public_key[i] < 16) if(self_public_key[i] < 16)
printf("0"); printf("0");
printf("%hhX",self_public_key[i]); printf("%hhX",self_public_key[i]);
@ -142,8 +152,8 @@ int main(int argc, char *argv[])
scanf("%s", temp_id); scanf("%s", temp_id);
DHT_addfriend(hex_string_to_bin(temp_id)); DHT_addfriend(hex_string_to_bin(temp_id));
//initialize networking /* initialize networking */
//bind to ip 0.0.0.0:PORT /* bind to ip 0.0.0.0:PORT */
IP ip; IP ip;
ip.i = 0; ip.i = 0;
init_networking(ip, PORT); init_networking(ip, PORT);
@ -152,10 +162,10 @@ int main(int argc, char *argv[])
perror("Initialization"); perror("Initialization");
IP_Port bootstrap_ip_port; IP_Port bootstrap_ip_port;
bootstrap_ip_port.port = htons(atoi(argv[2])); bootstrap_ip_port.port = htons(atoi(argv[2]));
//bootstrap_ip_port.ip.c[0] = 127; /* bootstrap_ip_port.ip.c[0] = 127;
//bootstrap_ip_port.ip.c[1] = 0; * bootstrap_ip_port.ip.c[1] = 0;
//bootstrap_ip_port.ip.c[2] = 0; * bootstrap_ip_port.ip.c[2] = 0;
//bootstrap_ip_port.ip.c[3] = 1; * bootstrap_ip_port.ip.c[3] = 1; */
bootstrap_ip_port.ip.i = inet_addr(argv[1]); bootstrap_ip_port.ip.i = inet_addr(argv[1]);
DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3]));
@ -163,20 +173,15 @@ int main(int argc, char *argv[])
uint8_t data[MAX_UDP_PACKET_SIZE]; uint8_t data[MAX_UDP_PACKET_SIZE];
uint32_t length; uint32_t length;
while(1) while(1) {
{
doDHT(); doDHT();
while(receivepacket(&ip_port, data, &length) != -1) while(receivepacket(&ip_port, data, &length) != -1) {
{ if(DHT_handlepacket(data, length, ip_port) && friendreq_handlepacket(data, length, ip_port)) {
if(DHT_handlepacket(data, length, ip_port) && friendreq_handlepacket(data, length, ip_port))
{
//unhandled packet //unhandled packet
printpacket(data, length, ip_port); printpacket(data, length, ip_port);
} } else {
else
{
printf("Received handled packet with length: %u\n", length); printf("Received handled packet with length: %u\n", length);
} }
} }
@ -187,4 +192,4 @@ int main(int argc, char *argv[])
shutdown_networking(); shutdown_networking();
return 0; return 0;
} }

View File

@ -8,6 +8,24 @@
* *
* Command line arguments are the ip and port to connect and send the file to. * Command line arguments are the ip and port to connect and send the file to.
* EX: ./testclient 127.0.0.1 33445 filename.txt * EX: ./testclient 127.0.0.1 33445 filename.txt
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/ */
#include "../core/network.h" #include "../core/network.h"
@ -24,7 +42,6 @@
#endif #endif
#define PORT 33446 #define PORT 33446
void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port) void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port)
@ -32,8 +49,7 @@ void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port)
uint32_t i; uint32_t i;
printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length);
printf("--------------------BEGIN-----------------------------\n"); printf("--------------------BEGIN-----------------------------\n");
for(i = 0; i < length; i++) for(i = 0; i < length; i++) {
{
if(data[i] < 16) if(data[i] < 16)
printf("0"); printf("0");
printf("%hhX",data[i]); printf("%hhX",data[i]);
@ -99,39 +115,34 @@ void printconnection(int connection_id)
} }
*/ */
//recieve packets and send them to the packethandler
//run doLossless_UDP(); /*( recieve packets and send them to the packethandler */
/*run doLossless_UDP(); */
void Lossless_UDP() void Lossless_UDP()
{ {
IP_Port ip_port; IP_Port ip_port;
uint8_t data[MAX_UDP_PACKET_SIZE]; uint8_t data[MAX_UDP_PACKET_SIZE];
uint32_t length; uint32_t length;
while(receivepacket(&ip_port, data, &length) != -1) while(receivepacket(&ip_port, data, &length) != -1) {
{
printf("packet with length: %u\n", length); printf("packet with length: %u\n", length);
//if(rand() % 3 != 1)//add packet loss /* if(rand() % 3 != 1)//add packet loss
// { { */
if(LosslessUDP_handlepacket(data, length, ip_port)) if(LosslessUDP_handlepacket(data, length, ip_port)) {
{
printpacket(data, length, ip_port); printpacket(data, length, ip_port);
} } else {
else
{
//printconnection(0); //printconnection(0);
printf("Received handled packet with length: %u\n", length); printf("Received handled packet with length: %u\n", length);
} }
// } /* } */
} }
doLossless_UDP(); doLossless_UDP();
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if (argc < 4) if (argc < 4) {
{
printf("usage: %s ip port filename\n", argv[0]); printf("usage: %s ip port filename\n", argv[0]);
exit(0); exit(0);
} }
@ -143,8 +154,8 @@ int main(int argc, char *argv[])
if ( file==NULL ){return 1;} if ( file==NULL ){return 1;}
//initialize networking /* initialize networking */
//bind to ip 0.0.0.0:PORT /* bind to ip 0.0.0.0:PORT */
IP ip; IP ip;
ip.i = 0; ip.i = 0;
init_networking(ip, PORT); init_networking(ip, PORT);
@ -155,17 +166,14 @@ int main(int argc, char *argv[])
printip(serverip); printip(serverip);
int connection = new_connection(serverip); int connection = new_connection(serverip);
uint64_t timer = current_time(); uint64_t timer = current_time();
while(1) while(1) {
{ /* printconnection(connection); */
// printconnection(connection);
Lossless_UDP(); Lossless_UDP();
if(is_connected(connection) == 3) if(is_connected(connection) == 3) {
{
printf("Connecting took: %llu us\n", (unsigned long long)(current_time() - timer)); printf("Connecting took: %llu us\n", (unsigned long long)(current_time() - timer));
break; break;
} }
if(is_connected(connection) == 0) if(is_connected(connection) == 0) {
{
printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer)); printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer));
return 1; return 1;
} }
@ -174,38 +182,32 @@ int main(int argc, char *argv[])
timer = current_time(); timer = current_time();
//read first part of file /*read first part of file */
read = fread(buffer, 1, 512, file); read = fread(buffer, 1, 512, file);
while(1) while(1) {
{ /* printconnection(connection); */
//printconnection(connection);
Lossless_UDP(); Lossless_UDP();
if(is_connected(connection) == 3) if(is_connected(connection) == 3) {
{
if(write_packet(connection, buffer, read)) if(write_packet(connection, buffer, read)) {
{ /* printf("Wrote data.\n"); */
//printf("Wrote data.\n");
read = fread(buffer, 1, 512, file); read = fread(buffer, 1, 512, file);
} }
//printf("%u\n", sendqueue(connection)); /* printf("%u\n", sendqueue(connection)); */
if(sendqueue(connection) == 0) if(sendqueue(connection) == 0) {
{ if(read == 0) {
if(read == 0)
{
printf("Sent file successfully in: %llu us\n", (unsigned long long)(current_time() - timer)); printf("Sent file successfully in: %llu us\n", (unsigned long long)(current_time() - timer));
break; break;
} }
} }
} }
else else {
{
printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer));
return 0; return 0;
} }
//c_sleep(1); /* c_sleep(1); */
} }
return 0; return 0;

View File

@ -8,6 +8,24 @@
* *
* Command line argument is the name of the file to save what we recieve to. * Command line argument is the name of the file to save what we recieve to.
* EX: ./testserver filename1.txt * EX: ./testserver filename1.txt
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/ */
#include "../core/network.h" #include "../core/network.h"
@ -25,7 +43,6 @@
#endif #endif
#define PORT 33445 #define PORT 33445
void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port) void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port)
@ -33,14 +50,14 @@ void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port)
uint32_t i; uint32_t i;
printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length);
printf("--------------------BEGIN-----------------------------\n"); printf("--------------------BEGIN-----------------------------\n");
for(i = 0; i < length; i++) for(i = 0; i < length; i++) {
{
if(data[i] < 16) if(data[i] < 16)
printf("0"); printf("0");
printf("%hhX",data[i]); printf("%hhX",data[i]);
} }
printf("\n--------------------END-----------------------------\n\n\n"); printf("\n--------------------END-----------------------------\n\n\n");
} }
/* /*
void printpackets(Data test) void printpackets(Data test)
{ {
@ -95,23 +112,20 @@ void printconnection(int connection_id)
} }
*/ */
//recieve packets and send them to the packethandler
//run doLossless_UDP(); /* recieve packets and send them to the packethandler
* run doLossless_UDP(); */
void Lossless_UDP() void Lossless_UDP()
{ {
IP_Port ip_port; IP_Port ip_port;
uint8_t data[MAX_UDP_PACKET_SIZE]; uint8_t data[MAX_UDP_PACKET_SIZE];
uint32_t length; uint32_t length;
while(receivepacket(&ip_port, data, &length) != -1) while(receivepacket(&ip_port, data, &length) != -1) {
{
//if(rand() % 3 != 1)//add packet loss //if(rand() % 3 != 1)//add packet loss
//{ //{
if(LosslessUDP_handlepacket(data, length, ip_port)) if(LosslessUDP_handlepacket(data, length, ip_port)) {
{
printpacket(data, length, ip_port); printpacket(data, length, ip_port);
} } else {
else
{
//printconnection(0); //printconnection(0);
printf("Received handled packet with length: %u\n", length); printf("Received handled packet with length: %u\n", length);
} }
@ -119,14 +133,12 @@ void Lossless_UDP()
} }
doLossless_UDP(); doLossless_UDP();
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if (argc < 2) if (argc < 2) {
{
printf("usage: %s filename\n", argv[0]); printf("usage: %s filename\n", argv[0]);
exit(0); exit(0);
} }
@ -149,14 +161,11 @@ int main(int argc, char *argv[])
uint64_t timer = current_time(); uint64_t timer = current_time();
while(1) while(1) {
{
Lossless_UDP(); Lossless_UDP();
connection = incoming_connection(); connection = incoming_connection();
if(connection != -1) if(connection != -1) {
{ if(is_connected(connection) == 2) {
if(is_connected(connection) == 2)
{
printf("Recieved the connection.\n"); printf("Recieved the connection.\n");
} }
@ -167,25 +176,20 @@ int main(int argc, char *argv[])
timer = current_time(); timer = current_time();
while(1) while(1) {
{
//printconnection(0); //printconnection(0);
Lossless_UDP(); Lossless_UDP();
if(is_connected(connection) >= 2) if(is_connected(connection) >= 2) {
{
kill_connection_in(connection, 3000000); kill_connection_in(connection, 3000000);
read = read_packet(connection, buffer); read = read_packet(connection, buffer);
if(read != 0) if(read != 0) {
{
// printf("Recieved data.\n"); // printf("Recieved data.\n");
if(!fwrite(buffer, read, 1, file)) if(!fwrite(buffer, read, 1, file)) {
{
printf("file write error\n"); printf("file write error\n");
} }
} }
} }
if(is_connected(connection) == 4) if(is_connected(connection) == 4) {
{
printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer));
fclose(file); fclose(file);
return 1; return 1;

View File

@ -17,7 +17,24 @@
* Or the argument can be the path to the save file. * Or the argument can be the path to the save file.
* *
* EX: ./test Save.bak * EX: ./test Save.bak
* *
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/ */
#include "../core/Messenger.h" #include "../core/Messenger.h"
@ -33,14 +50,14 @@
#endif #endif
//horrible function from one of my first C programs. //TODO: rewrite
//only here because I was too lazy to write a proper one.
unsigned char * hex_string_to_bin(char hex_string[]) unsigned char * hex_string_to_bin(char hex_string[])
{ {
unsigned char * val = malloc(strlen(hex_string)); size_t len = strlen(hex_string);
unsigned char * val = malloc(len);
char * pos = hex_string; char * pos = hex_string;
int i=0; int i=0;
while(i < strlen(hex_string)) while(i < len)
{ {
sscanf(pos,"%2hhx",&val[i]); sscanf(pos,"%2hhx",&val[i]);
pos+=2; pos+=2;
@ -87,15 +104,12 @@ int main(int argc, char *argv[])
exit(0); exit(0);
} }
initMessenger(); initMessenger();
if(argc > 3) if(argc > 3) {
{
IP_Port bootstrap_ip_port; IP_Port bootstrap_ip_port;
bootstrap_ip_port.port = htons(atoi(argv[2])); bootstrap_ip_port.port = htons(atoi(argv[2]));
bootstrap_ip_port.ip.i = inet_addr(argv[1]); bootstrap_ip_port.ip.i = inet_addr(argv[1]);
DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3]));
} } else {
else
{
FILE *file = fopen(argv[1], "rb"); FILE *file = fopen(argv[1], "rb");
if ( file==NULL ){return 1;} if ( file==NULL ){return 1;}
int read; int read;
@ -110,8 +124,7 @@ int main(int argc, char *argv[])
printf("OUR ID: "); printf("OUR ID: ");
uint32_t i; uint32_t i;
for(i = 0; i < 32; i++) for(i = 0; i < 32; i++) {
{
if(self_public_key[i] < 16) if(self_public_key[i] < 16)
printf("0"); printf("0");
printf("%hhX",self_public_key[i]); printf("%hhX",self_public_key[i]);
@ -121,16 +134,14 @@ int main(int argc, char *argv[])
char temp_id[128]; char temp_id[128];
printf("\nEnter the client_id of the friend you wish to add (32 bytes HEX format):\n"); printf("\nEnter the client_id of the friend you wish to add (32 bytes HEX format):\n");
if(scanf("%s", temp_id) != 1) if(scanf("%s", temp_id) != 1) {
{
return 1; return 1;
} }
int num = m_addfriend(hex_string_to_bin(temp_id), (uint8_t*)"Install Gentoo", sizeof("Install Gentoo")); int num = m_addfriend(hex_string_to_bin(temp_id), (uint8_t*)"Install Gentoo", sizeof("Install Gentoo"));
perror("Initialization"); perror("Initialization");
while(1) while(1) {
{
uint8_t name[128]; uint8_t name[128];
getname(num, name); getname(num, name);
printf("%s\n", name); printf("%s\n", name);
@ -145,6 +156,5 @@ int main(int argc, char *argv[])
fwrite(buffer, 1, Messenger_size(), file); fwrite(buffer, 1, Messenger_size(), file);
free(buffer); free(buffer);
fclose(file); fclose(file);
} }
} }

View File

@ -1,3 +1,26 @@
/* nTox.c
*
* Textual frontend for Tox.
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/
#include "nTox.h" #include "nTox.h"
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
@ -23,12 +46,14 @@ void new_lines(char *line)
do_refresh(); do_refresh();
} }
//TODO: rewrite
unsigned char * hex_string_to_bin(char hex_string[]) unsigned char * hex_string_to_bin(char hex_string[])
{ {
unsigned char * val = malloc(strlen(hex_string)); size_t len = strlen(hex_string);
unsigned char * val = malloc(len);
char * pos = hex_string; char * pos = hex_string;
int i=0; int i=0;
while(i < strlen(hex_string)) while(i < len)
{ {
sscanf(pos,"%2hhx",&val[i]); sscanf(pos,"%2hhx",&val[i]);
pos+=2; pos+=2;
@ -58,7 +83,7 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
doMessenger(); doMessenger();
} else if (line[1] == 'm') { //message command: /m friendnumber messsage } else if (line[1] == 'm') { //message command: /m friendnumber messsage
int i; int i;
int len = strlen(line); size_t len = strlen(line);
char numstring[len-3]; char numstring[len-3];
char message[len-3]; char message[len-3];
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
@ -77,7 +102,8 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
} else if (line[1] == 'n') { } else if (line[1] == 'n') {
uint8_t name[MAX_NAME_LENGTH]; uint8_t name[MAX_NAME_LENGTH];
int i = 0; int i = 0;
for (i=3; i<strlen(line); i++) { size_t len = strlen(line);
for (i=3; i<len; i++) {
if (line[i] == 0 || line[i] == '\n') break; if (line[i] == 0 || line[i] == '\n') break;
name[i - 3] = line[i]; name[i - 3] = line[i];
} }
@ -89,7 +115,8 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
} else if (line[1] == 's') { } else if (line[1] == 's') {
uint8_t status[MAX_USERSTATUS_LENGTH]; uint8_t status[MAX_USERSTATUS_LENGTH];
int i = 0; int i = 0;
for (i=3; i<strlen(line); i++) { size_t len = strlen(line);
for (i=3; i<len; i++) {
if (line[i] == 0 || line[i] == '\n') break; if (line[i] == 0 || line[i] == '\n') break;
status[i - 3] = line[i]; status[i - 3] = line[i];
} }
@ -111,7 +138,8 @@ void wrap(char output[STRING_LENGTH], char input[STRING_LENGTH], int line_width)
{ {
int i = 0; int i = 0;
strcpy(output,input); strcpy(output,input);
for (i=line_width; i < strlen(output); i = i + line_width) { size_t len = strlen(output);
for (i=line_width; i < len; i = i + line_width) {
while (output[i] != ' ' && i != 0) { while (output[i] != ' ' && i != 0) {
i--; i--;
} }
@ -123,7 +151,7 @@ void wrap(char output[STRING_LENGTH], char input[STRING_LENGTH], int line_width)
int count_lines(char *string) int count_lines(char *string)
{ {
int len = strlen(string); size_t len = strlen(string);
int i; int i;
int count = 1; int count = 1;
for (i=0; i < len; i++) { for (i=0; i < len; i++) {
@ -136,7 +164,7 @@ int count_lines(char *string)
char *appender(char *str, const char c) char *appender(char *str, const char c)
{ {
int len = strlen(str); size_t len = strlen(str);
if (len < STRING_LENGTH) { if (len < STRING_LENGTH) {
str[len + 1] = str[len]; str[len + 1] = str[len];
str[len] = c; str[len] = c;
@ -167,6 +195,7 @@ void do_refresh()
clrtoeol(); clrtoeol();
refresh(); refresh();
} }
void print_request(uint8_t * public_key, uint8_t * data, uint16_t length) void print_request(uint8_t * public_key, uint8_t * data, uint16_t length)
{ {
new_lines("[i] received friend request"); new_lines("[i] received friend request");
@ -182,6 +211,7 @@ void print_request(uint8_t * public_key, uint8_t * data, uint16_t length)
new_lines(numchar); new_lines(numchar);
} }
} }
void print_message(int friendnumber, uint8_t * string, uint16_t length) void print_message(int friendnumber, uint8_t * string, uint16_t length)
{ {
char name[MAX_NAME_LENGTH]; char name[MAX_NAME_LENGTH];
@ -192,11 +222,12 @@ void print_message(int friendnumber, uint8_t * string, uint16_t length)
time ( &rawtime ); time ( &rawtime );
timeinfo = localtime ( &rawtime ); timeinfo = localtime ( &rawtime );
char* temp = asctime(timeinfo); char* temp = asctime(timeinfo);
int len = strlen(temp); size_t len = strlen(temp);
temp[len-1]='\0'; temp[len-1]='\0';
sprintf(msg, "[%d] %s <%s> %s", friendnumber, temp, name, string); // someone please fix this sprintf(msg, "[%d] %s <%s> %s", friendnumber, temp, name, string); // someone please fix this
new_lines(msg); new_lines(msg);
} }
void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) { void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) {
char name[MAX_NAME_LENGTH]; char name[MAX_NAME_LENGTH];
getname(friendnumber, (uint8_t*)name); getname(friendnumber, (uint8_t*)name);
@ -204,6 +235,7 @@ void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) {
sprintf(msg, "[i] [%d] %s is now known as %s.", friendnumber, name, string); sprintf(msg, "[i] [%d] %s is now known as %s.", friendnumber, name, string);
new_lines(msg); new_lines(msg);
} }
void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) { void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) {
char name[MAX_NAME_LENGTH]; char name[MAX_NAME_LENGTH];
getname(friendnumber, (uint8_t*)name); getname(friendnumber, (uint8_t*)name);
@ -211,6 +243,7 @@ void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) {
sprintf(msg, "[i] [%d] %s's status changed to %s.", friendnumber, name, string); sprintf(msg, "[i] [%d] %s's status changed to %s.", friendnumber, name, string);
new_lines(msg); new_lines(msg);
} }
void load_key(){ void load_key(){
FILE *data_file = NULL; FILE *data_file = NULL;
if ((data_file = fopen("data","r"))) { if ((data_file = fopen("data","r"))) {
@ -237,6 +270,7 @@ void load_key(){
} }
fclose(data_file); fclose(data_file);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if (argc < 4) { if (argc < 4) {
@ -294,9 +328,7 @@ int main(int argc, char *argv[])
DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3]));
nodelay(stdscr, TRUE); nodelay(stdscr, TRUE);
while(true) { while(true) {
if (on == 0 && DHT_isconnected()) {
if (on == 0 && DHT_isconnected())
{
new_lines("[i] connected to DHT\n[i] define username with /n"); new_lines("[i] connected to DHT\n[i] define username with /n");
on = 1; on = 1;
} }

View File

@ -1,3 +1,26 @@
/* nTox.h
*
*Textual frontend for Tox.
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* 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/>.
*
*/
#ifndef NTOX_H #ifndef NTOX_H
#define NTOX_H #define NTOX_H