Merge remote-tracking branch 'ProjectTox/master'

This commit is contained in:
Astonex 2013-07-31 23:02:09 +01:00
commit f05aa30870
47 changed files with 1148 additions and 268 deletions

8
.gitignore vendored
View File

@ -12,3 +12,11 @@ install_manifest.txt
testing/data
*~
# Object files
*.o
# Executables
*.exe
*.out
*.app

View File

@ -11,12 +11,17 @@ before_script:
- ./autogen.sh
- ./configure && make check -j3
- sudo make install
- sudo ldconfig
- 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
- wget http://www.hyperrealm.com/libconfig/libconfig-1.4.9.tar.gz
- tar -xvzf libconfig-1.4.9.tar.gz
- cd libconfig-1.4.9
- ./configure && make -j3
- sudo make install
- cd ..
# creating librarys' links and updating cache
- sudo ldconfig
script:
- mkdir build && cd build

24
CMakeLists.txt Normal file → Executable file
View File

@ -1,11 +1,31 @@
cmake_minimum_required(VERSION 2.6.0)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
if(NOT WIN32)
option(USE_NACL "Use NaCl library instead of libsodium")
endif()
if(USE_NACL)
find_package(NaCl REQUIRED)
include_directories(${NACL_INCLUDE_DIR})
add_definitions(-DVANILLA_NACL)
set(LINK_CRYPTO_LIBRARY ${NACL_LIBRARIES})
endif()
#MinGW prints more warnings for -Wall than gcc does, thus causing build to fail
if(NOT WIN32)
if(("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang"))
message(STATUS "==== ${CMAKE_C_COMPILER_ID} detected - Adding compiler flags ====")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror")
endif()
find_package(SODIUM REQUIRED)
endif()
if(NOT USE_NACL)
set(LINK_CRYPTO_LIBRARY ${SODIUM_LIBRARY})
endif()
macro(linkCoreLibraries exe_name)
@ -16,8 +36,10 @@ macro(linkCoreLibraries exe_name)
${CMAKE_SOURCE_DIR}/sodium/lib/libsodium.a
ws2_32)
else()
include_directories(${SODIUM_INCLUDE_DIR})
target_link_libraries(${exe_name} core
sodium)
${LINK_CRYPTO_LIBRARY})
endif()
endmacro()

View File

@ -5,8 +5,9 @@
Build dependencies:
```bash
apt-get install build-essential libtool autotools-dev automake libconfig-dev ncurses-dev
apt-get install build-essential libtool autotools-dev automake libconfig-dev ncurses-dev cmake checkinstall
```
Note that `libconfig-dev` should be >= 1.4.
You should get and install [libsodium](https://github.com/jedisct1/libsodium):
```bash
@ -15,7 +16,7 @@ cd libsodium
git checkout tags/0.4.2
./autogen.sh
./configure && make check
sudo make install
sudo checkinstall --install --pkgname libsodium --pkgversion 0.4.2 --nodoc
sudo ldconfig
```
@ -41,7 +42,17 @@ make
###OSX:
Much the same as above, remember to install the latest XCode and the developer tools (Preferences -> Downloads -> Command Line Tools).
####Homebrew:
```
brew install libtool automake autoconf libconfig libsodium
cmake .
make
sudo make install
```
####Non-homebrew:
Much the same as Linux, remember to install the latest XCode and the developer tools (Preferences -> Downloads -> Command Line Tools).
Users running Mountain Lion and the latest version of XCode (4.6.3) will also need to install libtool, automake and autoconf.
They are easy enough to install, grab them from http://www.gnu.org/software/libtool/, http://www.gnu.org/software/autoconf/ and http://www.gnu.org/software/automake/, then follow these steps for each:
@ -68,7 +79,7 @@ You have to [modify your PATH environment variable](http://www.computerhope.com/
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 package of libsodium from [here](https://download.libsodium.org/libsodium/releases/libsodium-win32-0.4.2.tar.gz) and extract the archive into this repo's root. That is, `sodium` folder should be along with `core`, `testing` and other folders.
Navigate in `cmd` to this repo and run:
```cmd

View File

@ -1,54 +1,51 @@
![Project Tox](https://rbt.asia/boards/g/img/0352/79/1373823047559.png "Project Tox")
Project Tox, _also known as Tox_, is a FOSS instant messaging application aimed to replace Skype.<br />
Project Tox, _also known as Tox_, is a FOSS (Free and Open Source Software) instant messaging application aimed to replace Skype.<br />
With the rise of governmental monitoring programs, Tox aims to be an easy to use application that allows people to connect with friends and loved ones without the worry of privacy.<br /> <br />
With the rise of governmental monitoring programs, Tox aims to be an easy to use, all-in-one communication platform (including audio, and videochats in the future) that ensures their users full privacy and secure message delivery.<br /> <br />
**IRC**: #tox on Freenode, alternatively, you can use the [webchat](http://webchat.freenode.net/?channels=#tox).<br />
**IRC**: #tox on freenode, alternatively, you can use the [webchat](http://webchat.freenode.net/?channels=#tox).<br />
**Website**: [http://tox.im](http://tox.im)
**Website translations**: [see stal888's repository](https://github.com/stal888/ProjectTox-Website)<br/>
**Qt GUI**: [see nurupo's repository](https://github.com/nurupo/ProjectTox-Qt-GUI)
**How to build Tox on Linux**: [YouTube video](http://www.youtube.com/watch?v=M4WXE4VKmyg)<br />
**How to use Tox on Windows**: [YouTube video](http://www.youtube.com/watch?v=qg_j_sDb6WQ)
### Objectives:
Keep everything really simple.
## The Complex Stuff:
+ Tox must use UDP simply because you can't hole punch with TCP. It's possible, but it doesn't work all the time.
+ Every peer is represented as a byte string (the public key of the peer [client id])
+ Tox must use UDP simply because [hole punching](http://en.wikipedia.org/wiki/UDP_hole_punching) with TCP is not as reliable.
+ Every peer is represented as a [byte string](https://en.wikipedia.org/wiki/String_(computer_science)) (the public key of the peer [client ID]).
+ We're using torrent-style DHT so that peers can find the IP of the other peers when they have their ID.
+ Once the client has the IP of that peer, they start initiating a secure connection with each other. (See [Crypto](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto)
+ When both peers are securely connect with the encryption, they can securely exchange messages, initiate a video chat, send files, etc.<br />
+ Once the client has the IP of that peer, they start initiating a secure connection with each other. (See [Crypto](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto))
+ When both peers are securely connected, they can exchange messages, initiate a video chat, send files, etc, all using encrypted communications.
+ Current build status: [![Build Status](https://travis-ci.org/irungentoo/ProjectTox-Core.png?branch=master)](https://travis-ci.org/irungentoo/ProjectTox-Core)
## Roadmap:
- [x] Get our DHT working perfectly.(Done, needs large scale testing though.)
- [x] Reliable connection (See Lossless_UDP protocol) to other peers according to client id. (Done, see DHT_sendfiletest.c for an example)
- [x] Get our DHT working perfectly. (Done, needs large scale testing though)
- [x] Reliable connection (See Lossless UDP protocol) to other peers according to client ID. (Done, see DHT_sendfiletest.c for an example)
- [x] Encryption. (Done)
- [ ] Get a simple text only im client working perfectly. (This is where we are)
- [ ] Get a simple text only IM client working perfectly. (This is where we are)
- [ ] Streaming media
- [ ] ???
For further information, check our [To-do list](https://github.com/irungentoo/ProjectTox-Core/wiki/TODO)
### Why are you doing this? There are already a bunch of free skype alternatives.
The goal of this project is to create a configuration-free P2P skype
replacement. Configuration-free means that the user will simply have to open the program and
without any account configuration will be capable of adding people to his
friends list and start conversing with them. There are many so called skype replacements and all of them are either hard to
configure for the normal user or suffer from being way too centralized.
### Important-stuff:
Use the same UDP socket for everything
Keep everything really simple.
### Details and Documents:
### Documentation:
[DHT Protocol](https://github.com/irungentoo/ProjectTox-Core/wiki/DHT)<br />
[Lossless UDP Protocol](https://github.com/irungentoo/ProjectTox-Core/wiki/Lossless-UDP)<br />
[Crypto](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto)<br />
[Ideas](https://github.com/irungentoo/ProjectTox-Core/wiki/Ideas)
### Why are you doing this? There are already a bunch of free skype alternatives.
The goal of this project is to create a configuration-free p2p skype
replacement. Configuration-free means that the user will simply have to open the program and
without any account configuration will be capable of adding people to his
friends list and start conversing with them. There are many so called skype replacements and all of them are either hard to
configure for the normal user or suffer from being much too centralized.

15
cmake/FindLIBCONFIG.cmake Normal file
View File

@ -0,0 +1,15 @@
# Find LIBCONFIG
#
# LIBCONFIG_INCLUDE_DIR
# LIBCONFIG_LIBRARY
# LIBCONFIG_FOUND
#
FIND_PATH(LIBCONFIG_INCLUDE_DIR NAMES libconfig.h)
FIND_LIBRARY(LIBCONFIG_LIBRARY NAMES config)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBCONFIG DEFAULT_MSG LIBCONFIG_LIBRARY LIBCONFIG_INCLUDE_DIR)
MARK_AS_ADVANCED(LIBCONFIG_INCLUDE_DIR LIBCONFIG_LIBRARY)

17
cmake/FindNaCl.cmake Normal file
View File

@ -0,0 +1,17 @@
find_path(NACL_INCLUDE_DIR crypto_box.h
$ENV{NACL_INCLUDE_DIR} /usr/include/nacl/
DOC "Directory which contain NaCl headers")
find_path(NACL_LIBRARY_DIR libnacl.a
$ENV{NACL_LIBRARY_DIR} /usr/lib/nacl
DOC "Directory which contain libnacl.a, cpucycles.o, and randombytes.o")
if(NACL_LIBRARY_DIR)
set(NACL_LIBRARIES
"${NACL_LIBRARY_DIR}/cpucycles.o"
"${NACL_LIBRARY_DIR}/libnacl.a"
"${NACL_LIBRARY_DIR}/randombytes.o")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NaCl DEFAULT_MSG NACL_INCLUDE_DIR NACL_LIBRARY_DIR NACL_LIBRARIES)

15
cmake/FindSODIUM.cmake Normal file
View File

@ -0,0 +1,15 @@
# Find SODIUM
#
# SODIUM_INCLUDE_DIR
# SODIUM_LIBRARY
# SODIUM_FOUND
#
FIND_PATH(SODIUM_INCLUDE_DIR NAMES sodium.h)
FIND_LIBRARY(SODIUM_LIBRARY NAMES sodium)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SODIUM DEFAULT_MSG SODIUM_LIBRARY SODIUM_INCLUDE_DIR)
MARK_AS_ADVANCED(SODIUM_INCLUDE_DIR SODIUM_LIBRARY)

View File

@ -3,6 +3,8 @@ project(core C)
if(WIN32)
include_directories(${CMAKE_HOME_DIRECTORY}/sodium/include/)
else(WIN32)
include_directories(${SODIUM_INCLUDE_DIR})
endif()
set(core_sources

View File

@ -308,12 +308,16 @@ IP_Port connection_ip(int connection_id)
/* returns the number of packets in the queue waiting to be successfully sent. */
uint32_t sendqueue(int connection_id)
{
if (connection_id < 0 || connection_id >= MAX_CONNECTIONS)
return 0;
return connections[connection_id].sendbuff_packetnum - connections[connection_id].successful_sent;
}
/* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */
uint32_t recvqueue(int connection_id)
{
if (connection_id < 0 || connection_id >= MAX_CONNECTIONS)
return 0;
return connections[connection_id].recv_packetnum - connections[connection_id].successful_read;
}
@ -321,6 +325,8 @@ uint32_t recvqueue(int connection_id)
return -1 if no packet in queue */
char id_packet(int connection_id)
{
if (connection_id < 0 || connection_id >= MAX_CONNECTIONS)
return -1;
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 -1;

View File

@ -99,18 +99,21 @@ int getclient_id(int friend_id, uint8_t *client_id)
client_id is the client id of the friend
data is the data and length is the length
returns the friend number if success
return -1 if failure. */
return -1 if key length is wrong.
return -2 if user's own key
return -3 if already a friend
return -4 for other*/
int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
{
if (length == 0 || length >=
(MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES))
return -1;
if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0)
return -1;
return -2;
if (getfriend_id(client_id) != -1)
return -1;
return -3;
uint32_t i;
for (i = 0; i <= numfriends; ++i) {
for (i = 0; i <= numfriends; ++i) { /*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/
if(friendlist[i].status == 0) {
DHT_addfriend(client_id);
friendlist[i].status = 1;
@ -126,7 +129,7 @@ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
return i;
}
}
return -1;
return -4;
}
int m_addfriend_norequest(uint8_t * client_id)
@ -134,7 +137,7 @@ int m_addfriend_norequest(uint8_t * client_id)
if (getfriend_id(client_id) != -1)
return -1;
uint32_t i;
for (i = 0; i <= numfriends; ++i) {
for (i = 0; i <= numfriends; ++i) {/*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/
if(friendlist[i].status == 0) {
DHT_addfriend(client_id);
friendlist[i].status = 2;
@ -165,7 +168,7 @@ int m_delfriend(int friendnumber)
uint32_t i;
for (i = numfriends; i != 0; --i) {
if (friendlist[i].status != 0)
if (friendlist[i-1].status != 0)
break;
}
numfriends = i;
@ -180,7 +183,7 @@ int m_delfriend(int friendnumber)
return 0 if there is no friend with that number */
int m_friendstatus(int friendnumber)
{
if (friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS)
if (friendnumber < 0 || friendnumber >= numfriends)
return 0;
return friendlist[friendnumber].status;
}
@ -190,7 +193,7 @@ int m_friendstatus(int friendnumber)
return 0 if it was not */
int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length)
{
if (friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS)
if (friendnumber < 0 || friendnumber >= numfriends)
return 0;
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. */
@ -242,6 +245,16 @@ int setname(uint8_t * name, uint16_t length)
return 0;
}
/* get our nickname
put it in name
name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
return the length of the name */
uint16_t getself_name(uint8_t *name)
{
memcpy(name, self_name, self_name_length);
return self_name_length;
}
/* get name of friendnumber
put it in name
name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.

View File

@ -50,7 +50,10 @@ extern "C" {
client_id is the client id of the friend
data is the data and length is the length
returns the friend number if success
return -1 if failure. */
return -1 if key length is wrong.
return -2 if user's own key
return -3 if already a friend
return -4 for other*/
int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length);
@ -92,6 +95,11 @@ int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length);
return -1 if failure */
int setname(uint8_t *name, uint16_t length);
/* get our nickname
put it in name
return the length of the name*/
uint16_t getself_name(uint8_t *name);
/* get name of friendnumber
put it in name
name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.

View File

@ -169,7 +169,7 @@ void shutdown_networking()
address should represent IPv4, IPv6 or a hostname
on success returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i
on failure returns -1 */
int resolve_addr(char *address)
int resolve_addr(const char *address)
{
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
@ -178,7 +178,7 @@ int resolve_addr(char *address)
struct addrinfo *server = NULL;
int success = getaddrinfo(address, "7", &hints, &server);
int success = getaddrinfo(address, "echo", &hints, &server);
if(success != 0)
return -1;

View File

@ -56,11 +56,7 @@
/* we use libsodium by default */
#include <sodium.h>
#else
/* TODO: Including stuff like this is bad. This needs fixing.
We keep support for the original NaCl for now. */
#include "../nacl/build/Linux/include/amd64/crypto_box.h"
#include <crypto_box.h>
#endif
#ifdef __cplusplus
@ -125,7 +121,7 @@ void shutdown_networking();
address should represent IPv4, IPv6 or a hostname
on success returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i
on failure returns -1 */
int resolve_addr(char *address);
int resolve_addr(const char *address);
#ifdef __cplusplus
}

25
docs/commands.md Normal file
View File

@ -0,0 +1,25 @@
# Tox User Commands
Here's a list of commands that nTox accepts,
which can all be used by starting your line with
a */*. Currently there can be no spaces before this.
* */f* [ID]
+ Add a friend with ID [ID].
* */d*
+ Call doMessenger() which does...something?
* */m* \[FRIEND\_NUM\] \[MESSAGE\]
+ Message \[FRIEND\_NUM\] \[MESSAGE\].
* */n* \[NAME\]
+ Change your username to \[NAME\].
* */l*
+ Print your list of friends. (like you have any)
* */s* \[STATUS\]
+ Set your status to \[STATUS\].
* */a* \[ID\]
+ Accept friend request from \[ID\].
* */i*
+ Print useful info about your client.
* */h*
+ Print some help.
* */q/*
+ Quit Tox. (why ;_;)

38
docs/using_tox.md Normal file
View File

@ -0,0 +1,38 @@
# Using Tox
1. Build Tox
2. Fix errors
3. Consult IRC for help
4. Go on debugging journy for devs
5. Build Tox for real
6. ???
For all the work we've put into Tox so far,
there isn't yet a decent guide for how you _use_
Tox. Here's a user-friendly attempt at it.
1. Connect to the network!
+ You need to connect to a bootstrapping server, to give you a public key.
+ Where can I find a public server? Right here, as of now:
(the help message from running nTox with no args will help)
+ 198.46.136.167 33445 728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854
+ 192.81.133.111 33445 8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858
+ 66.175.223.88 33445 AC4112C975240CAD260BB2FCD134266521FAAF0A5D159C5FD3201196191E4F5D
+ 192.184.81.118 33445 5CD7EB176C19A2FD840406CD56177BB8E75587BB366F7BB3004B19E3EDC04143
2. Find a friend!
+ Now that you're on the network, you need a friend. To get one of those,
you need to to send or receive a request. What's a request, you ask?
It's like a friend request, but we use really scary and cryptic numbers
instead of names. When nTox starts, it shows your _your_ long, scary number,
called your *public key*. Give that to people, and they can add you as
as "friend". Or, you can add someone else, with the */f* command, if you like.
3. Chat it up!
+ Now use the */m* command to send a message to someone. Wow, you're chatting!
4. But something broke!
+ Yeah, pre-alpha-alpha software tends to do that. We're working on it.
+ Please report all crashes to either the github page, or #tox-dev on freenode.
5. Nothing broke, but what does */f* mean?
+ nTox parses text as a command if the first character is a forward-slash ('/').
You can check all commands in commands.md.
6. Use and support Tox!
+ Code for us, debug for us, document for us, translate for us, even just talk about us!
+ The more interest we get, the more work gets done, the better Tox is.

View File

@ -3,8 +3,17 @@ project(DHT_bootstrap_daemon C)
set(exe_name DHT_bootstrap_daemon)
find_package(LIBCONFIG REQUIRED)
include_directories(${LIBCONFIG_INCLUDE_DIR})
add_executable(${exe_name}
DHT_bootstrap_daemon.c)
target_link_libraries(${exe_name} config)
target_link_libraries(${exe_name}
${LIBCONFIG_LIBRARY})
linkCoreLibraries(${exe_name})
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
find_package(LibConfig REQUIRED)

View File

@ -123,11 +123,12 @@ void manage_keys(char *keys_file)
{
const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
uint8_t keys[KEYS_SIZE];
struct stat existence;
FILE *keysf;
/* 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 */
/* Check if file exits, proceed to open and load keys */
if(stat(keys_file,&existence) >= 0) {
keysf = fopen(keys_file, "r");
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");

View File

@ -0,0 +1,73 @@
#Ref: https://github.com/schnorr/pajeng/blob/master/cmake/FindLibConfig.cmake
#
# This module defines
# LIBCONFIG_INCLUDE_DIR, where to find cppunit include files, etc.
# LIBCONFIG_LIBRARIES, the libraries to link against to use CppUnit.
# LIBCONFIG_STATIC_LIBRARIY_PATH
# LIBCONFIG_FOUND, If false, do not try to use CppUnit.
# also defined, but not for general use are
# LIBCONFIG_LIBRARY, where to find the CUnit library.
#MESSAGE("Searching for libconfig library")
FIND_PATH(LIBCONFIG_INCLUDE_DIR libconfig.h
/usr/local/include
/usr/include
)
FIND_PATH(LIBCONFIGPP_INCLUDE_DIR libconfig.h++
/usr/local/include
/usr/include
)
FIND_LIBRARY(LIBCONFIG_LIBRARY config
/usr/local/lib
/usr/lib
)
FIND_LIBRARY(LIBCONFIGPP_LIBRARY config++
/usr/local/lib
/usr/lib
)
FIND_LIBRARY(LIBCONFIG_STATIC_LIBRARY "libconfig${CMAKE_STATIC_LIBRARY_SUFFIX}"
/usr/local/lib
/usr/lib
)
FIND_LIBRARY(LIBCONFIGPP_STATIC_LIBRARY "libconfig++${CMAKE_STATIC_LIBRARY_SUFFIX}"
/usr/local/lib
/usr/lib
)
IF(LIBCONFIG_INCLUDE_DIR)
IF(LIBCONFIG_LIBRARY)
SET(LIBCONFIG_FOUND TRUE)
SET(LIBCONFIG_LIBRARIES ${LIBCONFIG_LIBRARY})
SET(LIBCONFIG_STATIC_LIBRARY_PATH ${LIBCONFIG_STATIC_LIBRARY})
ENDIF(LIBCONFIG_LIBRARY)
ENDIF(LIBCONFIG_INCLUDE_DIR)
IF(LIBCONFIGPP_INCLUDE_DIR)
IF(LIBCONFIGPP_LIBRARY)
SET(LIBCONFIGPP_FOUND TRUE)
SET(LIBCONFIGPP_LIBRARIES ${LIBCONFIGPP_LIBRARY})
SET(LIBCONFIGPP_STATIC_LIBRARY_PATH ${LIBCONFIGPP_STATIC_LIBRARY})
ENDIF(LIBCONFIGPP_LIBRARY)
ENDIF(LIBCONFIGPP_INCLUDE_DIR)
IF (LIBCONFIG_FOUND)
IF (NOT LibConfig_FIND_QUIETLY)
MESSAGE(STATUS "Found LibConfig++: ${LIBCONFIGPP_LIBRARIES}" )
MESSAGE(STATUS "Found LibConfig: ${LIBCONFIG_LIBRARIES}")
MESSAGE(STATUS "static LibConfig path: ${LIBCONFIG_STATIC_LIBRARY_PATH}")
ENDIF (NOT LibConfig_FIND_QUIETLY)
ELSE (LIBCONFIG_FOUND)
IF (LibConfig_FIND_REQUIRED)
MESSAGE(SEND_ERROR "Could NOT find LibConfig")
ENDIF (LibConfig_FIND_REQUIRED)
ENDIF (LIBCONFIG_FOUND)
MARK_AS_ADVANCED(LIBCONFIG_INCLUDE_DIR LIBCONFIG_LIBRARIES)

View File

@ -6,11 +6,15 @@ port = 33445;
// The key file
// make sure that the user who runs the server
// does have permissions to read it/write to it
// Remember to replace the provided example with
// the directory the DHT server will run in.
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
// Remember to replace the provided example with
// the directory the DHT server will run in.
pid_file = "/home/tom/.bootstrap_server.pid";
// The info of the node bootstap_server will

View File

@ -4,6 +4,7 @@ project(DHT_bootstrap C)
set(exe_name DHT_bootstrap)
add_executable(${exe_name}
DHT_bootstrap.c ../testing/misc_tools.c)
DHT_bootstrap.c
../testing/misc_tools.c)
linkCoreLibraries(${exe_name})

40
start_guide.de.md Normal file
View File

@ -0,0 +1,40 @@
# Tox nutzen
1. Tox erstellen
2. Fehler korrigieren
3. Im IRC nach Hilfe fragen
4. Auf Debug-Reise für Entwickler
5. Tox wirklich erstellen
6. ???
Trotz der ganzen Arbeit, die wir bisher in Tox
gesteckt haben, gibt es noch keine richtige
Anleitung, wie man Tox _benutzt_.
Dies ist ein anwenderfreundlicher Versuch.
1. Verbinde dich zum Netzwerk!
+ Du musst dich zu einem Bootstrap-Server verbinden, um einen öffentlichen Schlüssel zu erhalten.
+ Wo finde ich einen öffentlichen Server? Zur Zeit hier:
(die Hilfe-Nachricht von nTox ohne Kommandos hilft auch)
+ 198.46.136.167 33445 728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854
+ 192.81.133.111 33445 8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858
+ 66.175.223.88 33445 AC4112C975240CAD260BB2FCD134266521FAAF0A5D159C5FD3201196191E4F5D
+ 192.184.81.118 33445 5CD7EB176C19A2FD840406CD56177BB8E75587BB366F7BB3004B19E3EDC04143
2. Finde einen Freund!
+ Jetzt, da du im Netzwerk bist, brauchst du einen Freund. Um einen zu bekommen,
musst du eine Anfrage senden oder erhalten. Was eine Anfrage ist?
Es ist wie eine Freundschaftsanfrage, jedoch benutzen wir unglaublich schaurige
und kryptische Nummern anstatt Namen. When nTox startet, erscheint _deine_ lange,
schaurige Nummer, auch *öffentlicher Schlüssel* genannt. Diesen kannst du an
andere Personen weitergeben und sie können dich als "Freund" hinzufügen. Oder du
fügst andere Personen mit dem */f*-Befehl hinzu, wenn du möchtest.
3. Chatte drauf los!
+ Benutze nun den */m*-Befehl, um eine Nachricht an jemanden zu senden. Wow, du chattest!
4. Mach etwas kaputt!
+ Jep, pre-alpha-alpha-Software stürzt manchmal ab. Wir arbeiten daran.
+ Bitte melde alle Abstürze entweder an die GitHub-Seite oder #tox-dev im freenode-IRC.
5. Nichts ist kaputt, aber was bedeutet */f*?
+ nTox liest einen Text als Befehl, wenn das erste Zeichen ein Schrägstrich ist ('/').
Du kannst alle Befehle in commands.md nachlesen.
6. Benutze und unterstütze Tox!
+ Programmiere, debugge, dokumentiere, übersetze für uns, oder sprich einfach über uns!
+ Je mehr Interesse wir erhalten, desto mehr Arbeit wird getan und desto besser wird Tox.

38
start_guide.md Normal file
View File

@ -0,0 +1,38 @@
# Using Tox
1. Build Tox
2. Fix errors
3. Consult IRC for help
4. Go on debugging journy for devs
5. Build Tox for real
6. ???
For all the work we've put into Tox so far,
there isn't yet a decent guide for how you _use_
Tox. Here's a user-friendly attempt at it.
1. Connect to the network!
+ You need to connect to a bootstrapping server, to give you a public key.
+ Where can I find a public server? Right here, as of now:
(the help message from running nTox with no args will help)
+ 198.46.136.167 33445 728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854
+ 192.81.133.111 33445 8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858
+ 66.175.223.88 33445 AC4112C975240CAD260BB2FCD134266521FAAF0A5D159C5FD3201196191E4F5D
+ 192.184.81.118 33445 5CD7EB176C19A2FD840406CD56177BB8E75587BB366F7BB3004B19E3EDC04143
2. Find a friend!
+ Now that you're on the network, you need a friend. To get one of those,
you need to to send or receive a request. What's a request, you ask?
It's like a friend request, but we use really scary and cryptic numbers
instead of names. When nTox starts, it shows your _your_ long, scary number,
called your *public key*. Give that to people, and they can add you as
as "friend". Or, you can add someone else, with the */f* command, if you like.
3. Chat it up!
+ Now use the */m* command to send a message to someone. Wow, you're chatting!
4. But something broke!
+ Yeah, pre-alpha-alpha software tends to do that. We're working on it.
+ Please report all crashes to either the github page, or #tox-dev on freenode.
5. Nothing broke, but what does */f* mean?
+ nTox parses text as a command if the first character is a forward-slash ('/').
You can check all commands in commands.md.
6. Use and support Tox!
+ Code for us, debug for us, document for us, translate for us, even just talk about us!
+ The more interest we get, the more work gets done, the better Tox is.

View File

@ -11,8 +11,8 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Messenger_test.cmake)
if(WIN32)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nTox_win32.cmake)
endif()
if(NOT WIN32)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nTox.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/toxic.cmake)
add_subdirectory(toxic)
endif()

View File

@ -87,7 +87,7 @@ void print_friendlist()
for(i = 0; i < 4; i++) {
printf("ClientID: ");
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(friends_list[k].client_list[i].client_id[j] < 16)
printf("0");
printf("%hhX", friends_list[k].client_list[i].client_id[j]);
}
@ -134,7 +134,9 @@ int main(int argc, char *argv[])
char temp_id[128];
printf("\nEnter the client_id of the friend you wish to add (32 bytes HEX format):\n");
scanf("%s", temp_id);
if(scanf("%s", temp_id) != 1)
exit(0);
DHT_addfriend(hex_string_to_bin(temp_id));
/* initialize networking */

View File

@ -4,6 +4,7 @@ project(DHT_cryptosendfiletest C)
set(exe_name DHT_cryptosendfiletest)
add_executable(${exe_name}
DHT_cryptosendfiletest.c misc_tools.c)
DHT_cryptosendfiletest.c
misc_tools.c)
linkCoreLibraries(${exe_name})

View File

@ -4,6 +4,7 @@ project(DHT_test C)
set(exe_name DHT_test)
add_executable(${exe_name}
DHT_test.c misc_tools.c)
DHT_test.c
misc_tools.c)
linkCoreLibraries(${exe_name})

View File

@ -6,6 +6,7 @@ set(exe_name nTox)
add_executable(${exe_name}
nTox.c misc_tools.c)
target_link_libraries(${exe_name} ncurses)
target_link_libraries(${exe_name}
ncurses)
linkCoreLibraries(${exe_name})

View File

@ -20,12 +20,12 @@
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "nTox.h"
#include "misc_tools.h"
#include <stdio.h>
#include <time.h>
#ifdef WIN32
#define c_sleep(x) Sleep(1*x)
#else
@ -35,10 +35,14 @@
char lines[HISTORY][STRING_LENGTH];
char line[STRING_LENGTH];
char *help = "[i] commands: /f ID (to add friend), /m friendnumber message (to send message), /s status (to change status)\n"
"[i] /l list (list friends), /h for help, /i for info, /n nick (to change nickname), /q (to quit)";
int x, y;
uint8_t pending_requests[256][CLIENT_ID_SIZE];
uint8_t num_requests;
uint8_t num_requests = 0;
void new_lines(char *line)
{
@ -50,13 +54,53 @@ void new_lines(char *line)
do_refresh();
}
void print_friendlist()
{
char name[MAX_NAME_LENGTH];
new_lines("[i] Friend List:");
uint32_t i;
for (i = 0; i <= num_requests; i++) {
char fstring[128];
getname(i, (uint8_t*)name);
if (strlen(name) <= 0) {
sprintf(fstring, "[i] Friend: NULL\n\tid: %i", i);
} else {
sprintf(fstring, "[i] Friend: %s\n\tid: %i", (uint8_t*)name, i);
}
new_lines(fstring);
}
}
char *format_message(char *message, int friendnum)
{
char name[MAX_NAME_LENGTH];
if (friendnum != -1) {
getname(friendnum, (uint8_t*)name);
} else {
getself_name((uint8_t*)name);
}
char *msg = malloc(100+strlen(message)+strlen(name)+1);
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
char* time = asctime(timeinfo);
size_t len = strlen(time);
time[len-1] = '\0';
sprintf(msg, "[%d] %s <%s> %s", friendnum, time, name, message); // timestamp
return msg;
}
void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
{
if (line[0] == '/') {
char command[STRING_LENGTH + 2] = "> ";
strcat(command, line);
new_lines(command);
if (line[1] == 'f') { // add friend command: /f ID
char inpt_command = line[1];
char prompt[STRING_LENGTH + 2] = "> ";
strcat(prompt, line);
new_lines(prompt);
if (inpt_command == 'f') { // add friend command: /f ID
int i;
char temp_id[128];
for (i = 0; i < 128; i++)
@ -67,20 +111,20 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
new_lines(numstring);
do_refresh();
}
else if (line[1] == 'd') {
else if (inpt_command == 'd') {
doMessenger();
}
else if (line[1] == 'm') { //message command: /m friendnumber messsage
int i;
else if (inpt_command == 'm') { //message command: /m friendnumber messsage
size_t len = strlen(line);
char numstring[len-3];
char message[len-3];
int i;
for (i = 0; i < len; i++) {
if (line[i+3] != ' ') {
numstring[i] = line[i+3];
} else {
int j;
for (j=i+1; j<len; j++)
for (j = (i+1); j < len; j++)
message[j-i-1] = line[j+3];
break;
}
@ -88,9 +132,11 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
int num = atoi(numstring);
if (m_sendmessage(num, (uint8_t*) message, sizeof(message)) != 1) {
new_lines("[i] could not send message");
} else {
new_lines(format_message(message, -1));
}
}
else if (line[1] == 'n') {
else if (inpt_command == 'n') {
uint8_t name[MAX_NAME_LENGTH];
int i = 0;
size_t len = strlen(line);
@ -104,7 +150,10 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
sprintf(numstring, "[i] changed nick to %s", (char*)name);
new_lines(numstring);
}
else if (line[1] == 's') {
else if (inpt_command == 'l') {
print_friendlist();
}
else if (inpt_command == 's') {
uint8_t status[MAX_USERSTATUS_LENGTH];
int i = 0;
size_t len = strlen(line);
@ -118,31 +167,65 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
sprintf(numstring, "[i] changed status to %s", (char*)status);
new_lines(numstring);
}
else if (line[1] == 'a') {
else if (inpt_command == 'a') {
uint8_t numf = atoi(line + 3);
char numchar[100];
int num = m_addfriend_norequest(pending_requests[numf]);
if (num != -1) {
sprintf(numchar, "[i] friend request %u accepted", numf);
new_lines(numchar);
int num = m_addfriend_norequest(pending_requests[numf]);
sprintf(numchar, "[i] added friendnumber %d", num);
new_lines(numchar);
do_refresh();
} else {
sprintf(numchar, "[i] failed to add friend");
new_lines(numchar);
}
else if (line[1] == 'q') { //exit
do_refresh();
}
else if (inpt_command == 'h') { //help
new_lines("[i] commands: /f ID (to add friend), /m friendnumber message (to send message), /s status (to change status)");
new_lines("[i] /l list (list friends), /h for help, /i for info, /n nick (to change nickname), /q (to quit)");
}
else if (inpt_command == 'i') { //info
char idstring0[200];
char idstring1[PUB_KEY_BYTES][5];
char idstring2[PUB_KEY_BYTES][5];
int i;
for (i = 0; i < PUB_KEY_BYTES; i++)
{
if (self_public_key[i] < (PUB_KEY_BYTES/2))
strcpy(idstring1[i],"0");
else
strcpy(idstring1[i], "");
sprintf(idstring2[i], "%hhX", self_public_key[i]);
}
//
strcpy(idstring0,"[i] ID: ");
int j;
for (j = 0; j < PUB_KEY_BYTES; j++) {
strcat(idstring0,idstring1[j]);
strcat(idstring0,idstring2[j]);
}
new_lines(idstring0);
}
else if (inpt_command == 'q') { //exit
endwin();
exit(EXIT_SUCCESS);
} else {
new_lines("[i] invalid command");
}
} else {
new_lines("[i] invalid command");
//new_lines(line);
}
}
void wrap(char output[STRING_LENGTH], char input[STRING_LENGTH], int line_width)
{
int i = 0;
strcpy(output,input);
size_t len = strlen(output);
int i = 0;
for (i = line_width; i < len; i = i + line_width) {
while (output[i] != ' ' && i != 0) {
i--;
@ -156,8 +239,8 @@ void wrap(char output[STRING_LENGTH], char input[STRING_LENGTH], int line_width)
int count_lines(char *string)
{
size_t len = strlen(string);
int i;
int count = 1;
int i;
for (i = 0; i < len; i++) {
if (string[i] == '\n')
count++;
@ -177,14 +260,14 @@ char *appender(char *str, const char c)
void do_refresh()
{
int i;
int count=0;
int l;
char wrap_output[STRING_LENGTH];
int L;
int i;
for (i = 0; i < HISTORY; i++) {
wrap(wrap_output, lines[i], x);
l = count_lines(wrap_output);
count = count + l;
L = count_lines(wrap_output);
count = count + L;
if (count < y) {
move(y-1-count, 0);
printw(wrap_output);
@ -224,10 +307,11 @@ void print_message(int friendnumber, uint8_t * string, uint16_t length)
size_t len = strlen(temp);
temp[len-1] = '\0';
sprintf(msg, "[%d] %s <%s> %s", friendnumber, temp, name, string); // timestamp
new_lines(msg);
new_lines(format_message((char*)string, friendnumber));
}
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];
getname(friendnumber, (uint8_t*)name);
char msg[100+length];
@ -235,7 +319,8 @@ void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) {
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];
getname(friendnumber, (uint8_t*)name);
char msg[100+length+strlen(name)+1];
@ -243,9 +328,11 @@ void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) {
new_lines(msg);
}
void load_key(){
void load_key()
{
FILE *data_file = NULL;
if ((data_file = fopen("data","r"))) {
data_file = fopen("data","r");
if (data_file) {
//load keys
fseek(data_file, 0, SEEK_END);
int size = ftell(data_file);
@ -292,28 +379,29 @@ int main(int argc, char *argv[])
m_callback_namechange(print_nickchange);
m_callback_userstatus(print_statuschange);
char idstring0[200];
char idstring1[32][5];
char idstring2[32][5];
uint32_t i;
for(i = 0; i < 32; i++)
char idstring1[PUB_KEY_BYTES][5];
char idstring2[PUB_KEY_BYTES][5];
int i;
for(i = 0; i < PUB_KEY_BYTES; i++)
{
if(self_public_key[i] < 16)
if (self_public_key[i] < (PUB_KEY_BYTES / 2))
strcpy(idstring1[i],"0");
else
strcpy(idstring1[i], "");
sprintf(idstring2[i], "%hhX",self_public_key[i]);
}
strcpy(idstring0,"[i] your ID: ");
for (i=0; i<32; i++) {
strcat(idstring0,idstring1[i]);
strcat(idstring0,idstring2[i]);
int j;
for (j = 0; j < PUB_KEY_BYTES; j++) {
strcat(idstring0,idstring1[j]);
strcat(idstring0,idstring2[j]);
}
initscr();
noecho();
raw();
getmaxyx(stdscr, y, x);
new_lines(idstring0);
new_lines("[i] commands: /f ID (to add friend), /m friendnumber message (to send message), /s status (to change status), /n nick (to change nickname), /q (to quit)");
new_lines(help);
strcpy(line, "");
IP_Port bootstrap_ip_port;
bootstrap_ip_port.port = htons(atoi(argv[2]));
@ -336,7 +424,6 @@ int main(int argc, char *argv[])
do_refresh();
c = getch();
if (c == ERR || c == 27)
continue;

View File

@ -39,6 +39,7 @@
#include "../core/network.h"
#define STRING_LENGTH 256
#define HISTORY 50
#define PUB_KEY_BYTES 32
void new_lines(char *line);
void line_eval(char lines[HISTORY][STRING_LENGTH], char *line);

View File

@ -27,7 +27,7 @@
#include <process.h>
uint8_t pending_requests[256][CLIENT_ID_SIZE];
uint8_t num_requests;
uint8_t num_requests = 0;
char line[STRING_LENGTH];
char users_id[200];
@ -89,13 +89,12 @@ void print_statuschange(int friendnumber, uint8_t *string, uint16_t length)
void load_key()
{
FILE *data_file = NULL;
if ((data_file = fopen("data", "r"))) {
data_file = fopen("data","r");
if (data_file) {
fseek(data_file, 0, SEEK_END);
int size = ftell(data_file);
fseek(data_file, 0, SEEK_SET);
uint8_t data[size];
if (fread(data, sizeof(uint8_t), size, data_file) != size) {
printf("\n[i] Could not read the data file. Exiting.");
exit(1);
@ -113,15 +112,15 @@ void load_key()
exit(1);
}
}
fclose(data_file);
}
void line_eval(char* line)
{
if(line[0] == '/') {
char inpt_command = line[1];
/* Add friend */
if(line[1] == 'f') {
if(inpt_command == 'f') {
int i;
char temp_id[128];
for (i = 0; i < 128; i++)
@ -132,16 +131,15 @@ void line_eval(char* line)
printf(numstring);
}
else if (line[1] == 'r') {
else if (inpt_command == 'r') {
do_header();
printf("\n\n");
}
else if (line[1] == 'l') {
else if (inpt_command == 'l') {
printf("\n[i] Friend List | Total: %d\n\n", getnumfriends());
int i;
for (i = 0; i < getnumfriends(); i++) {
char name[MAX_NAME_LENGTH];
getname(i, (uint8_t*)name);
@ -152,7 +150,7 @@ void line_eval(char* line)
}
}
else if (line[1] == 'd') {
else if (inpt_command == 'd') {
size_t len = strlen(line);
char numstring[len-3];
int i;
@ -166,17 +164,17 @@ void line_eval(char* line)
printf("\n\n");
}
/* Send message to friend */
else if (line[1] == 'm') {
int i;
else if (inpt_command == 'm') {
size_t len = strlen(line);
char numstring[len-3];
char message[len-3];
int i;
for (i = 0; i < len; i++) {
if (line[i+3] != ' ') {
numstring[i] = line[i+3];
} else {
int j;
for (j=i+1; j<len; j++)
for (j = (i+1); j < len; j++)
message[j-i-1] = line[j+3];
break;
}
@ -190,7 +188,7 @@ void line_eval(char* line)
}
}
else if (line[1] == 'n') {
else if (inpt_command == 'n') {
uint8_t name[MAX_NAME_LENGTH];
int i = 0;
size_t len = strlen(line);
@ -205,7 +203,7 @@ void line_eval(char* line)
printf(numstring);
}
else if (line[1] == 's') {
else if (inpt_command == 's') {
uint8_t status[MAX_USERSTATUS_LENGTH];
int i = 0;
size_t len = strlen(line);
@ -220,7 +218,7 @@ void line_eval(char* line)
printf(numstring);
}
else if (line[1] == 'a') {
else if (inpt_command == 'a') {
uint8_t numf = atoi(line + 3);
char numchar[100];
sprintf(numchar, "\n[i] friend request %u accepted\n\n", numf);
@ -230,12 +228,10 @@ void line_eval(char* line)
printf(numchar);
}
/* EXIT */
else if (line[1] == 'q') {
else if (inpt_command == 'q') {
exit(EXIT_SUCCESS);
}
}
else {
} else {
//nothing atm
}
}
@ -255,12 +251,10 @@ int main(int argc, char *argv[])
printf("[!] Usage: %s [IP] [port] [public_key] <nokey>\n", argv[0]);
exit(0);
}
if (initMessenger() == -1) {
printf("initMessenger failed");
exit(0);
}
if (argc > 4) {
if(strncmp(argv[4], "nokey", 6) < 0) {
}
@ -272,26 +266,25 @@ int main(int argc, char *argv[])
m_callback_friendmessage(print_message);
m_callback_namechange(print_nickchange);
m_callback_userstatus(print_statuschange);
char idstring1[32][5];
char idstring2[32][5];
uint32_t i;
for(i = 0; i < 32; i++)
char idstring1[PUB_KEY_BYTES][5];
char idstring2[PUB_KEY_BYTES][5];
int i;
for(i = 0; i < PUB_KEY_BYTES; i++)
{
if(self_public_key[i] < 16)
if(self_public_key[i] < (PUB_KEY_BYTES/2))
strcpy(idstring1[i],"0");
else
strcpy(idstring1[i], "");
sprintf(idstring2[i], "%hhX",self_public_key[i]);
}
strcpy(users_id,"[i] your ID: ");
for (i=0; i<32; i++) {
strcat(users_id,idstring1[i]);
strcat(users_id,idstring2[i]);
int j;
for (j = 0; j < PUB_KEY_BYTES; j++) {
strcat(users_id,idstring1[j]);
strcat(users_id,idstring2[j]);
}
do_header();
IP_Port bootstrap_ip_port;
bootstrap_ip_port.port = htons(atoi(argv[2]));
int resolved_address = resolve_addr(argv[1]);
@ -301,12 +294,9 @@ int main(int argc, char *argv[])
exit(1);
DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3]));
int c;
int on = 0;
_beginthread(get_input, 0, NULL);
while(1) {
if (on == 1 && DHT_isconnected() == -1) {
printf("\n---------------------------------");
@ -314,16 +304,13 @@ int main(int argc, char *argv[])
printf("\n---------------------------------\n\n");
on = 0;
}
if (on == 0 && DHT_isconnected()) {
printf("\n[i] Connected to DHT");
printf("\n---------------------------------\n\n");
on = 1;
}
doMessenger();
Sleep(1);
}
return 0;
}

View File

@ -27,6 +27,7 @@
#include "../core/network.h"
#define STRING_LENGTH 256
#define PUB_KEY_BYTES 32
void do_header();
void print_message(int friendnumber, uint8_t * string, uint16_t length);

View File

@ -4,8 +4,12 @@ project(toxic C)
set(exe_name toxic)
add_executable(${exe_name}
toxic/main.c toxic/prompt.c)
main.c
prompt.c
friendlist.c
chat.c)
target_link_libraries(${exe_name} curses)
target_link_libraries(${exe_name}
curses)
linkCoreLibraries(${exe_name})

155
testing/toxic/chat.c Normal file
View File

@ -0,0 +1,155 @@
/*
* Toxic -- Tox Curses Client
*/
#include <curses.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#include "../../core/Messenger.h"
#include "../../core/network.h"
#include "windows.h"
typedef struct {
int friendnum;
char line[256];
size_t pos;
WINDOW* history;
WINDOW* linewin;
} ChatContext;
extern void fix_name(uint8_t* name);
static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) {
ChatContext* ctx = (ChatContext*) self->x;
uint8_t nick[MAX_NAME_LENGTH] = {0};
if(ctx->friendnum != num)
return;
getname(num, (uint8_t*) &nick);
msg[len-1] = '\0';
nick[MAX_NAME_LENGTH-1] = '\0';
fix_name(msg);
fix_name(nick);
wattron(ctx->history, COLOR_PAIR(4));
wprintw(ctx->history, "%s: ", nick);
wattroff(ctx->history, COLOR_PAIR(4));
wprintw(ctx->history, "%s\n", msg);
self->blink = true;
}
static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t len) {
ChatContext* ctx = (ChatContext*) self->x;
if(ctx->friendnum != num)
return;
nick[len-1] = '\0';
fix_name(nick);
wattron(ctx->history, COLOR_PAIR(3));
wprintw(ctx->history, " * Your partner changed nick to '%s'\n", nick);
wattroff(ctx->history, COLOR_PAIR(3));
}
static void chat_onStatusChange(ToxWindow* self, int num, uint8_t* status, uint16_t len) {
}
static void chat_onKey(ToxWindow* self, int key) {
ChatContext* ctx = (ChatContext*) self->x;
if(isprint(key)) {
if(ctx->pos != sizeof(ctx->line)-1) {
ctx->line[ctx->pos++] = key;
ctx->line[ctx->pos] = '\0';
}
}
else if(key == '\n') {
wattron(ctx->history, COLOR_PAIR(1));
wprintw(ctx->history, "you: ", ctx->line);
wattroff(ctx->history, COLOR_PAIR(1));
wprintw(ctx->history, "%s\n", ctx->line);
if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) {
wattron(ctx->history, COLOR_PAIR(3));
wprintw(ctx->history, " * Failed to send message.\n");
wattroff(ctx->history, COLOR_PAIR(3));
}
ctx->line[0] = '\0';
ctx->pos = 0;
}
else if(key == 0x107 || key == 0x8 || key == 0x7f) {
if(ctx->pos != 0) {
ctx->line[--ctx->pos] = '\0';
}
}
}
static void chat_onDraw(ToxWindow* self) {
int x, y;
ChatContext* ctx = (ChatContext*) self->x;
getmaxyx(self->window, y, x);
(void) x;
if(y < 3)
return;
wclear(ctx->linewin);
mvwhline(ctx->linewin, 0, 0, '_', COLS);
mvwprintw(ctx->linewin, 1, 0, "%s\n", ctx->line);
wrefresh(self->window);
}
static void chat_onInit(ToxWindow* self) {
int x, y;
ChatContext* ctx = (ChatContext*) self->x;
getmaxyx(self->window, y, x);
ctx->history = subwin(self->window, y - 4, x, 0, 0);
scrollok(ctx->history, 1);
ctx->linewin = subwin(self->window, 2, x, y - 3, 0);
}
ToxWindow new_chat(int friendnum) {
ToxWindow ret;
memset(&ret, 0, sizeof(ret));
ret.onKey = &chat_onKey;
ret.onDraw = &chat_onDraw;
ret.onInit = &chat_onInit;
ret.onMessage = &chat_onMessage;
ret.onNickChange = &chat_onNickChange;
ret.onStatusChange = &chat_onStatusChange;
snprintf(ret.title, sizeof(ret.title), "[chat %d]", friendnum);
ChatContext* x = calloc(1, sizeof(ChatContext));
x->friendnum = friendnum;
ret.x = (void*) x;
return ret;
}

166
testing/toxic/friendlist.c Normal file
View File

@ -0,0 +1,166 @@
/*
* Toxic -- Tox Curses Client
*/
#include <curses.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#include "../../core/Messenger.h"
#include "../../core/network.h"
#include "windows.h"
extern int add_window(ToxWindow w);
extern int focus_window(int num);
extern ToxWindow new_chat(int friendnum);
#define MAX_FRIENDS_NUM 100
typedef struct {
uint8_t name[MAX_NAME_LENGTH];
uint8_t status[MAX_USERSTATUS_LENGTH];
int num;
int chatwin;
} friend_t;
static friend_t friends[MAX_FRIENDS_NUM];
static int num_friends = 0;
static int num_selected = 0;
void fix_name(uint8_t* name) {
// Remove all non alphanumeric characters.
uint8_t* p = name;
uint8_t* q = name;
while(*p != 0) {
if(isprint(*p)) {
*q++ = *p;
}
p++;
}
*q = 0;
}
void friendlist_onMessage(ToxWindow* self, int num, uint8_t* str, uint16_t len) {
if(num >= num_friends)
return;
if(friends[num].chatwin == -1) {
friends[num].chatwin = add_window(new_chat(num));
}
}
void friendlist_onNickChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) {
if(len >= MAX_NAME_LENGTH || num >= num_friends)
return;
memcpy((char*) &friends[num].name, (char*) str, len);
friends[num].name[len] = 0;
fix_name(friends[num].name);
}
void friendlist_onStatusChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) {
if(len >= MAX_USERSTATUS_LENGTH || num >= num_friends)
return;
memcpy((char*) &friends[num].status, (char*) str, len);
friends[num].status[len] = 0;
fix_name(friends[num].status);
}
int friendlist_onFriendAdded(int num) {
if(num_friends == MAX_FRIENDS_NUM)
return -1;
friends[num_friends].num = num;
getname(num, friends[num_friends].name);
strcpy((char*) friends[num_friends].name, "unknown");
strcpy((char*) friends[num_friends].status, "unknown");
friends[num_friends].chatwin = -1;
num_friends++;
return 0;
}
static void friendlist_onKey(ToxWindow* self, int key) {
if(key == KEY_UP) {
if(num_selected != 0)
num_selected--;
}
else if(key == KEY_DOWN) {
if(num_friends != 0)
num_selected = (num_selected+1) % num_friends;
}
else if(key == '\n') {
if(friends[num_selected].chatwin != -1)
return;
friends[num_selected].chatwin = add_window(new_chat(num_selected));
focus_window(friends[num_selected].chatwin);
}
}
static void friendlist_onDraw(ToxWindow* self) {
size_t i;
wclear(self->window);
if(num_friends == 0) {
wprintw(self->window, "Empty. Add some friends! :-)\n");
}
else {
wattron(self->window, COLOR_PAIR(2) | A_BOLD);
wprintw(self->window, "Open chat with.. (up/down keys, enter)\n");
wattroff(self->window, COLOR_PAIR(2) | A_BOLD);
}
wprintw(self->window, "\n");
for(i=0; i<num_friends; i++) {
if(i == num_selected) wattron(self->window, COLOR_PAIR(3));
wprintw(self->window, " [#%d] ", friends[i].num);
if(i == num_selected) wattroff(self->window, COLOR_PAIR(3));
attron(A_BOLD);
wprintw(self->window, "%s ", friends[i].name);
attroff(A_BOLD);
wprintw(self->window, "(%s)\n", friends[i].status);
}
wrefresh(self->window);
}
static void friendlist_onInit(ToxWindow* self) {
}
ToxWindow new_friendlist() {
ToxWindow ret;
memset(&ret, 0, sizeof(ret));
ret.onKey = &friendlist_onKey;
ret.onDraw = &friendlist_onDraw;
ret.onInit = &friendlist_onInit;
ret.onMessage = &friendlist_onMessage;
ret.onNickChange = &friendlist_onNickChange;
ret.onStatusChange = &friendlist_onStatusChange;
strcpy(ret.title, "[friends]");
return ret;
}

View File

@ -14,6 +14,10 @@
#include "windows.h"
extern ToxWindow new_prompt();
extern ToxWindow new_friendlist();
extern int friendlist_onFriendAdded(int num);
extern int add_req(uint8_t* public_key); // XXX
#define TOXWINDOWS_MAX_NUM 32
@ -25,21 +29,59 @@ static ToxWindow* prompt;
// CALLBACKS START
void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) {
size_t i;
int n = add_req(public_key);
wprintw(prompt->window, "\nFriend request.\nUse \"accept %d\" to accept it.\n", n);
wprintw(prompt->window, "\nFriend request from:\n");
for(i=0; i<32; i++) {
wprintw(prompt->window, "%02x", public_key[i] & 0xff);
}
wprintw(prompt->window, "\n");
wprintw(prompt->window, "Use \"accept %d\" to accept it.\n", n);
for(i=0; i<w_num; i++) {
if(windows[i].onFriendRequest != NULL)
windows[i].onFriendRequest(&windows[i], public_key, data, length);
}
}
void on_message(int friendnumber, uint8_t* string, uint16_t length) {
size_t i;
wprintw(prompt->window, "\n(message) %d: %s!\n", friendnumber, string);
for(i=0; i<w_num; i++) {
if(windows[i].onMessage != NULL)
windows[i].onMessage(&windows[i], friendnumber, string, length);
}
}
void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) {
wprintw(prompt->window, "\n(nick) %d: %s!\n", friendnumber, string);
size_t i;
wprintw(prompt->window, "\n(nickchange) %d: %s!\n", friendnumber, string);
for(i=0; i<w_num; i++) {
if(windows[i].onNickChange != NULL)
windows[i].onNickChange(&windows[i], friendnumber, string, length);
}
}
void on_statuschange(int friendnumber, uint8_t* string, uint16_t length) {
wprintw(prompt->window, "\n(status) %d: %s!\n", friendnumber, string);
size_t i;
wprintw(prompt->window, "\n(statuschange) %d: %s!\n", friendnumber, string);
for(i=0; i<w_num; i++) {
if(windows[i].onStatusChange != NULL)
windows[i].onStatusChange(&windows[i], friendnumber, string, length);
}
}
void on_friendadded(int friendnumber) {
friendlist_onFriendAdded(friendnumber);
}
// CALLBACKS END
@ -73,7 +115,7 @@ static void init_tox() {
m_callback_userstatus(on_statuschange);
}
static int add_window(ToxWindow w) {
int add_window(ToxWindow w) {
if(w_num == TOXWINDOWS_MAX_NUM)
return -1;
@ -88,14 +130,22 @@ static int add_window(ToxWindow w) {
windows[w_num++] = w;
w.onInit(&w);
return w_num;
return w_num - 1;
}
int focus_window(int num) {
if(num >= w_num || num < 0)
return -1;
w_active = num;
return 0;
}
static void init_windows() {
w_num = 0;
w_active = 0;
if(add_window(new_prompt()) == -1) {
if(add_window(new_prompt()) == -1 || add_window(new_friendlist()) == -1) {
fprintf(stderr, "add_window() failed.\n");
endwin();
@ -134,14 +184,18 @@ static void load_data() {
if(buf == NULL) {
fprintf(stderr, "malloc() failed.\n");
fclose(fd);
endwin();
exit(1);
}
if(fread(buf, len, 1, fd) != 1){
fprintf(stderr, "fread() failed.\n");
free(buf);
fclose(fd);
endwin();
exit(1);
}
@ -153,6 +207,7 @@ static void load_data() {
if(buf == NULL) {
fprintf(stderr, "malloc() failed.\n");
endwin();
exit(1);
}
@ -161,14 +216,18 @@ static void load_data() {
fd = fopen("data", "w");
if(fd == NULL) {
fprintf(stderr, "fopen() failed.\n");
free(buf);
endwin();
exit(1);
}
if(fwrite(buf, len, 1, fd) != 1){
fprintf(stderr, "fwrite() failed.\n");
free(buf);
fclose(fd);
endwin();
exit(1);
}
}
@ -178,6 +237,7 @@ static void load_data() {
}
static void draw_bar() {
static int odd = 0;
size_t i;
attron(COLOR_PAIR(4));
@ -186,13 +246,27 @@ static void draw_bar() {
move(LINES - 1, 0);
attron(COLOR_PAIR(4) | A_BOLD);
printw(" TOXIC 1.0 |");
attroff(COLOR_PAIR(4) | A_BOLD);
for(i=0; i<w_num; i++) {
if(i == w_active) {
attron(A_BOLD);
}
odd = (odd+1) % 2;
if(windows[i].blink && odd) {
attron(COLOR_PAIR(3));
}
printw(" %s", windows[i].title);
if(windows[i].blink && odd) {
attron(COLOR_PAIR(3));
}
if(i == w_active) {
attroff(A_BOLD);
}
@ -201,6 +275,11 @@ static void draw_bar() {
refresh();
}
void prepare_window(WINDOW* w) {
mvwin(w, 0, 0);
wresize(w, LINES-2, COLS);
}
int main(int argc, char* argv[]) {
int ch;
ToxWindow* a;
@ -211,14 +290,22 @@ int main(int argc, char* argv[]) {
init_windows();
while(true) {
// Update tox.
do_tox();
// Draw.
a = &windows[w_active];
prepare_window(a->window);
a->blink = false;
a->onDraw(a);
draw_bar();
// Handle input.
ch = getch();
if(ch != ERR) {
if(ch == '\t') {
w_active = (w_active + 1) % w_num;
}
else if(ch != ERR) {
a->onKey(a, ch);
}

View File

@ -15,6 +15,8 @@
uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX
uint8_t num_requests=0; // XXX
extern void on_friendadded(int friendnumber);
// XXX:
int add_req(uint8_t* public_key) {
memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE);
@ -40,8 +42,7 @@ static int prompt_buf_pos=0;
static void execute(ToxWindow* self, char* cmd) {
// quit/exit: Exit program.
if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit")) {
if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) {
endwin();
exit(0);
}
@ -53,33 +54,32 @@ static void execute(ToxWindow* self, char* cmd) {
ip = strchr(cmd, ' ');
if(ip == NULL) {
wprintw(self->window, "Invalid syntax.\n");
return;
}
ip++;
port = strchr(ip, ' ');
if(port == NULL) {
wprintw(self->window, "Invalid syntax.\n");
return;
}
port[0] = 0;
port++;
key = strchr(port, ' ');
if(key == NULL) {
wprintw(self->window, "Invalid syntax.\n");
return;
}
key[0] = 0;
key++;
if(atoi(port) == 0) {
wprintw(self->window, "Invalid syntax.\n");
return;
}
wprintw(self->window, "ip=%s, port=%s, key=%s\n", ip, port, key);
dht.port = htons(atoi(port));
int resolved_address = resolve_addr(ip);
@ -91,38 +91,62 @@ static void execute(ToxWindow* self, char* cmd) {
DHT_bootstrap(dht, hex_string_to_bin(key));
}
else if(!strncmp(cmd, "add ", strlen("add "))) {
uint8_t id_bin[32];
size_t i;
char xx[3];
uint32_t x;
char* id;
char* msg;
int num;
id = strchr(cmd, ' ');
if(id == NULL) {
wprintw(self->window, "Invalid syntax.\n");
return;
}
id++;
msg = strchr(id, ' ');
if(msg == NULL) {
if(msg != NULL) {
msg[0] = 0;
msg++;
}
else msg = "";
if(strlen(id) != 2*32) {
wprintw(self->window, "Invalid ID length.\n");
return;
}
msg[0] = 0;
msg++;
for(i=0; i<32; i++) {
xx[0] = id[2*i];
xx[1] = id[2*i+1];
xx[2] = '\0';
if(sscanf(xx, "%02x", &x) != 1) {
wprintw(self->window, "Invalid ID.\n");
return;
}
id_bin[i] = x;
}
num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1);
num = m_addfriend((uint8_t*) id, (uint8_t*) msg, strlen(msg)+1);
wprintw(self->window, "Friend added as %d.\n", num);
on_friendadded(num);
}
else if(!strncmp(cmd, "status ", strlen("status "))) {
char* msg;
msg = strchr(cmd, ' ');
if(msg == NULL) {
wprintw(self->window, "Invalid syntax.\n");
return;
}
msg++;
m_set_userstatus((uint8_t*) msg, strlen(msg)+1);
wprintw(self->window, "Status set to: %s.\n", msg);
}
@ -133,33 +157,22 @@ static void execute(ToxWindow* self, char* cmd) {
if(nick == NULL) {
return;
}
nick++;
setname((uint8_t*) nick, strlen(nick)+1);
wprintw(self->window, "Nickname set to: %s.\n", nick);
}
else if(!strcmp(cmd, "myid")) {
// XXX: Clean this up
char idstring0[200];
char idstring1[32][5];
char idstring2[32][5];
uint32_t i;
char id[32*2 + 1] = {0};
size_t i;
for(i=0; i<32; i++) {
if(self_public_key[i] < 16)
strcpy(idstring1[i], "0");
else
strcpy(idstring1[i], "");
sprintf(idstring2[i], "%hhX", self_public_key[i]);
char xx[3];
snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff);
strcat(id, xx);
}
for (i=0; i<32; i++) {
strcat(idstring0, idstring1[i]);
strcat(idstring0, idstring2[i]);
}
wprintw(self->window, "%s\n", idstring0);
wprintw(self->window, "%s\n", id);
}
else if(!strncmp(cmd, "accept ", strlen("accept "))) {
char* id;
@ -167,17 +180,26 @@ static void execute(ToxWindow* self, char* cmd) {
id = strchr(cmd, ' ');
if(id == NULL) {
wprintw(self->window, "Invalid syntax.\n");
return;
}
id++;
num = atoi(id);
if(num >= num_requests) {
wprintw(self->window, "Invalid syntax.\n");
return;
}
num = m_addfriend_norequest(pending_requests[num]);
if(num == -1) {
wprintw(self->window, "Failed to add friend.\n");
}
else {
wprintw(self->window, "Friend accepted as: %d.\n", num);
on_friendadded(num);
}
}
else if(!strncmp(cmd, "msg ", strlen("msg "))) {
char* id;
@ -186,26 +208,29 @@ static void execute(ToxWindow* self, char* cmd) {
id = strchr(cmd, ' ');
if(id == NULL) {
wprintw(self->window, "Invalid syntax.\n");
return;
}
id++;
msg = strchr(id, ' ');
if(msg == NULL) {
wprintw(self->window, "Invalid syntax.\n");
return;
}
msg[0] = 0;
msg++;
if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) != 1) {
if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) < 0) {
wprintw(self->window, "Error occurred while sending message.\n");
}
else {
wprintw(self->window, "Message successfully sent.\n");
}
}
else {
wprintw(self->window, "Invalid syntax.\n");
}
}
static void prompt_onKey(ToxWindow* self, int key) {
@ -231,7 +256,7 @@ static void prompt_onKey(ToxWindow* self, int key) {
}
// BACKSPACE key: Remove one character from line.
else if(key == 0x107) {
else if(key == 0x107 || key == 0x8 || key == 0x7f) {
if(prompt_buf_pos != 0) {
prompt_buf[--prompt_buf_pos] = 0;
@ -242,9 +267,6 @@ static void prompt_onKey(ToxWindow* self, int key) {
static void prompt_onDraw(ToxWindow* self) {
int x, y;
mvwin(self->window,0,0);
wresize(self->window, LINES-2, COLS);
getyx(self->window, y, x);
(void) x;
@ -260,7 +282,7 @@ static void prompt_onDraw(ToxWindow* self) {
static void print_usage(ToxWindow* self) {
wattron(self->window, COLOR_PAIR(2) | A_BOLD);
wprintw(self->window, "Usage:\n");
wprintw(self->window, "Commands:\n");
wattroff(self->window, A_BOLD);
wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n");
@ -270,6 +292,12 @@ static void print_usage(ToxWindow* self) {
wprintw(self->window, " accept <number> : Accept friend request\n");
wprintw(self->window, " myid : Print your ID\n");
wprintw(self->window, " quit/exit : Exit program\n");
wattron(self->window, A_BOLD);
wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n");
wattroff(self->window, A_BOLD);
wattroff(self->window, COLOR_PAIR(2));
}
@ -283,6 +311,8 @@ static void prompt_onInit(ToxWindow* self) {
ToxWindow new_prompt() {
ToxWindow ret;
memset(&ret, 0, sizeof(ret));
ret.onKey = &prompt_onKey;
ret.onDraw = &prompt_onDraw;
ret.onInit = &prompt_onInit;

View File

@ -1,10 +1,23 @@
/*
* Toxic -- Tox Curses Client
*/
#include <stdbool.h>
typedef struct ToxWindow_ ToxWindow;
struct ToxWindow_ {
void(*onKey)(ToxWindow*, int);
void(*onDraw)(ToxWindow*);
void(*onInit)(ToxWindow*);
void(*onFriendRequest)(ToxWindow*, uint8_t*, uint8_t*, uint16_t);
void(*onMessage)(ToxWindow*, int, uint8_t*, uint16_t);
void(*onNickChange)(ToxWindow*, int, uint8_t*, uint16_t);
void(*onStatusChange)(ToxWindow*, int, uint8_t*, uint16_t);
char title[256];
void* x;
bool blink;
WINDOW* window;
};