mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Merge remote-tracking branch 'ProjectTox/master'
This commit is contained in:
commit
f05aa30870
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -12,3 +12,11 @@ install_manifest.txt
|
||||||
|
|
||||||
testing/data
|
testing/data
|
||||||
*~
|
*~
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
13
.travis.yml
13
.travis.yml
|
@ -11,12 +11,17 @@ before_script:
|
||||||
- ./autogen.sh
|
- ./autogen.sh
|
||||||
- ./configure && make check -j3
|
- ./configure && make check -j3
|
||||||
- sudo make install
|
- sudo make install
|
||||||
- sudo ldconfig
|
|
||||||
- cd ..
|
- cd ..
|
||||||
# installing libconfig, needed for DHT_bootstrap_daemon
|
# installing libconfig, needed for DHT_bootstrap_daemon
|
||||||
- sudo sed -i 's/precise/quantal/' /etc/apt/sources.list # needed for libconfig-dev
|
- wget http://www.hyperrealm.com/libconfig/libconfig-1.4.9.tar.gz
|
||||||
- sudo apt-get update -qq
|
- tar -xvzf libconfig-1.4.9.tar.gz
|
||||||
- yes | sudo apt-get install libconfig-dev
|
- cd libconfig-1.4.9
|
||||||
|
- ./configure && make -j3
|
||||||
|
- sudo make install
|
||||||
|
- cd ..
|
||||||
|
# creating librarys' links and updating cache
|
||||||
|
- sudo ldconfig
|
||||||
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- mkdir build && cd build
|
- mkdir build && cd build
|
||||||
|
|
26
CMakeLists.txt
Normal file → Executable file
26
CMakeLists.txt
Normal file → Executable file
|
@ -1,11 +1,31 @@
|
||||||
cmake_minimum_required(VERSION 2.6.0)
|
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
|
#MinGW prints more warnings for -Wall than gcc does, thus causing build to fail
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
if(("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang"))
|
if(("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang"))
|
||||||
message(STATUS "==== ${CMAKE_C_COMPILER_ID} detected - Adding compiler flags ====")
|
message(STATUS "==== ${CMAKE_C_COMPILER_ID} detected - Adding compiler flags ====")
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror")
|
||||||
endif()
|
endif()
|
||||||
|
find_package(SODIUM REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT USE_NACL)
|
||||||
|
set(LINK_CRYPTO_LIBRARY ${SODIUM_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
macro(linkCoreLibraries exe_name)
|
macro(linkCoreLibraries exe_name)
|
||||||
|
@ -16,8 +36,10 @@ macro(linkCoreLibraries exe_name)
|
||||||
${CMAKE_SOURCE_DIR}/sodium/lib/libsodium.a
|
${CMAKE_SOURCE_DIR}/sodium/lib/libsodium.a
|
||||||
ws2_32)
|
ws2_32)
|
||||||
else()
|
else()
|
||||||
|
include_directories(${SODIUM_INCLUDE_DIR})
|
||||||
target_link_libraries(${exe_name} core
|
target_link_libraries(${exe_name} core
|
||||||
sodium)
|
${LINK_CRYPTO_LIBRARY})
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
@ -25,4 +47,4 @@ cmake_policy(SET CMP0011 NEW)
|
||||||
|
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
add_subdirectory(testing)
|
add_subdirectory(testing)
|
||||||
add_subdirectory(other)
|
add_subdirectory(other)
|
||||||
|
|
19
INSTALL.md
19
INSTALL.md
|
@ -5,8 +5,9 @@
|
||||||
Build dependencies:
|
Build dependencies:
|
||||||
|
|
||||||
```bash
|
```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):
|
You should get and install [libsodium](https://github.com/jedisct1/libsodium):
|
||||||
```bash
|
```bash
|
||||||
|
@ -15,7 +16,7 @@ cd libsodium
|
||||||
git checkout tags/0.4.2
|
git checkout tags/0.4.2
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure && make check
|
./configure && make check
|
||||||
sudo make install
|
sudo checkinstall --install --pkgname libsodium --pkgversion 0.4.2 --nodoc
|
||||||
sudo ldconfig
|
sudo ldconfig
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -41,7 +42,17 @@ make
|
||||||
|
|
||||||
###OSX:
|
###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.
|
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:
|
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.
|
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:
|
Navigate in `cmd` to this repo and run:
|
||||||
```cmd
|
```cmd
|
||||||
|
|
67
README.md
67
README.md
|
@ -1,54 +1,51 @@
|
||||||
![Project Tox](https://rbt.asia/boards/g/img/0352/79/1373823047559.png "Project Tox")
|
![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**: [http://tox.im](http://tox.im)
|
||||||
|
|
||||||
**Website translations**: [see stal888's repository](https://github.com/stal888/ProjectTox-Website)<br/>
|
**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)
|
**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:
|
||||||
## 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])
|
|
||||||
+ 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 />
|
|
||||||
+ 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] Encryption. (Done)
|
|
||||||
- [ ] 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)
|
|
||||||
|
|
||||||
|
|
||||||
### Important-stuff:
|
|
||||||
|
|
||||||
Use the same UDP socket for everything
|
|
||||||
|
|
||||||
Keep everything really simple.
|
Keep everything really simple.
|
||||||
|
|
||||||
### Details and Documents:
|
## The Complex Stuff:
|
||||||
|
+ 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 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] Encryption. (Done)
|
||||||
|
- [ ] 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.
|
||||||
|
|
||||||
|
### Documentation:
|
||||||
|
|
||||||
[DHT Protocol](https://github.com/irungentoo/ProjectTox-Core/wiki/DHT)<br />
|
[DHT Protocol](https://github.com/irungentoo/ProjectTox-Core/wiki/DHT)<br />
|
||||||
[Lossless UDP Protocol](https://github.com/irungentoo/ProjectTox-Core/wiki/Lossless-UDP)<br />
|
[Lossless UDP Protocol](https://github.com/irungentoo/ProjectTox-Core/wiki/Lossless-UDP)<br />
|
||||||
[Crypto](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto)<br />
|
[Crypto](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto)<br />
|
||||||
[Ideas](https://github.com/irungentoo/ProjectTox-Core/wiki/Ideas)
|
[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
15
cmake/FindLIBCONFIG.cmake
Normal 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
17
cmake/FindNaCl.cmake
Normal 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
15
cmake/FindSODIUM.cmake
Normal 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)
|
|
@ -3,15 +3,17 @@ project(core C)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
include_directories(${CMAKE_HOME_DIRECTORY}/sodium/include/)
|
include_directories(${CMAKE_HOME_DIRECTORY}/sodium/include/)
|
||||||
|
else(WIN32)
|
||||||
|
include_directories(${SODIUM_INCLUDE_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(core_sources
|
set(core_sources
|
||||||
DHT.c
|
DHT.c
|
||||||
network.c
|
network.c
|
||||||
Lossless_UDP.c
|
Lossless_UDP.c
|
||||||
net_crypto.c
|
net_crypto.c
|
||||||
friend_requests.c
|
friend_requests.c
|
||||||
LAN_discovery.c
|
LAN_discovery.c
|
||||||
Messenger.c)
|
Messenger.c)
|
||||||
|
|
||||||
add_library(core ${core_sources})
|
add_library(core ${core_sources})
|
||||||
|
|
|
@ -308,12 +308,16 @@ IP_Port connection_ip(int connection_id)
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
|
if (connection_id < 0 || connection_id >= MAX_CONNECTIONS)
|
||||||
|
return 0;
|
||||||
return connections[connection_id].sendbuff_packetnum - connections[connection_id].successful_sent;
|
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(...) */
|
/* 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)
|
||||||
{
|
{
|
||||||
|
if (connection_id < 0 || connection_id >= MAX_CONNECTIONS)
|
||||||
|
return 0;
|
||||||
return connections[connection_id].recv_packetnum - connections[connection_id].successful_read;
|
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 */
|
return -1 if no packet in queue */
|
||||||
char id_packet(int connection_id)
|
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)
|
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;
|
||||||
|
|
|
@ -99,18 +99,21 @@ int getclient_id(int friend_id, uint8_t *client_id)
|
||||||
client_id is the client id of the friend
|
client_id is the client id of the friend
|
||||||
data is the data and length is the length
|
data is the data and length is the length
|
||||||
returns the friend number if success
|
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)
|
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 -2;
|
||||||
if (getfriend_id(client_id) != -1)
|
if (getfriend_id(client_id) != -1)
|
||||||
return -1;
|
return -3;
|
||||||
uint32_t i;
|
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) {
|
if(friendlist[i].status == 0) {
|
||||||
DHT_addfriend(client_id);
|
DHT_addfriend(client_id);
|
||||||
friendlist[i].status = 1;
|
friendlist[i].status = 1;
|
||||||
|
@ -126,7 +129,7 @@ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
int m_addfriend_norequest(uint8_t * client_id)
|
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)
|
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) {/*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/
|
||||||
if(friendlist[i].status == 0) {
|
if(friendlist[i].status == 0) {
|
||||||
DHT_addfriend(client_id);
|
DHT_addfriend(client_id);
|
||||||
friendlist[i].status = 2;
|
friendlist[i].status = 2;
|
||||||
|
@ -165,7 +168,7 @@ int m_delfriend(int friendnumber)
|
||||||
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-1].status != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
numfriends = i;
|
numfriends = i;
|
||||||
|
@ -180,7 +183,7 @@ 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)
|
||||||
{
|
{
|
||||||
if (friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS)
|
if (friendnumber < 0 || friendnumber >= numfriends)
|
||||||
return 0;
|
return 0;
|
||||||
return friendlist[friendnumber].status;
|
return friendlist[friendnumber].status;
|
||||||
}
|
}
|
||||||
|
@ -190,7 +193,7 @@ int m_friendstatus(int friendnumber)
|
||||||
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 >= numfriends)
|
||||||
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. */
|
||||||
|
@ -242,6 +245,16 @@ int setname(uint8_t * name, uint16_t length)
|
||||||
return 0;
|
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
|
/* 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 bytes.
|
name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
|
||||||
|
|
|
@ -46,11 +46,14 @@ extern "C" {
|
||||||
to an absurdly large number later */
|
to an absurdly large number later */
|
||||||
|
|
||||||
/* 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
|
||||||
data is the data and length is the length
|
data is the data and length is the length
|
||||||
returns the friend number if success
|
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);
|
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 */
|
return -1 if failure */
|
||||||
int setname(uint8_t *name, uint16_t length);
|
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
|
/* 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.
|
||||||
|
|
|
@ -48,4 +48,4 @@ int friendreq_handlepacket(uint8_t *packet, uint32_t length, IP_Port source);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -169,7 +169,7 @@ void shutdown_networking()
|
||||||
address should represent IPv4, IPv6 or a hostname
|
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 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 */
|
on failure returns -1 */
|
||||||
int resolve_addr(char *address)
|
int resolve_addr(const char *address)
|
||||||
{
|
{
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
@ -178,7 +178,7 @@ int resolve_addr(char *address)
|
||||||
|
|
||||||
struct addrinfo *server = NULL;
|
struct addrinfo *server = NULL;
|
||||||
|
|
||||||
int success = getaddrinfo(address, "7", &hints, &server);
|
int success = getaddrinfo(address, "echo", &hints, &server);
|
||||||
if(success != 0)
|
if(success != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
|
@ -56,11 +56,7 @@
|
||||||
/* we use libsodium by default */
|
/* we use libsodium by default */
|
||||||
#include <sodium.h>
|
#include <sodium.h>
|
||||||
#else
|
#else
|
||||||
|
#include <crypto_box.h>
|
||||||
/* 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"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -125,7 +121,7 @@ void shutdown_networking();
|
||||||
address should represent IPv4, IPv6 or a hostname
|
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 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 */
|
on failure returns -1 */
|
||||||
int resolve_addr(char *address);
|
int resolve_addr(const char *address);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
25
docs/commands.md
Normal file
25
docs/commands.md
Normal 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
38
docs/using_tox.md
Normal 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.
|
|
@ -3,8 +3,17 @@ project(DHT_bootstrap_daemon C)
|
||||||
|
|
||||||
set(exe_name DHT_bootstrap_daemon)
|
set(exe_name DHT_bootstrap_daemon)
|
||||||
|
|
||||||
add_executable(${exe_name}
|
find_package(LIBCONFIG REQUIRED)
|
||||||
DHT_bootstrap_daemon.c)
|
|
||||||
|
include_directories(${LIBCONFIG_INCLUDE_DIR})
|
||||||
|
|
||||||
|
add_executable(${exe_name}
|
||||||
|
DHT_bootstrap_daemon.c)
|
||||||
|
|
||||||
|
target_link_libraries(${exe_name}
|
||||||
|
${LIBCONFIG_LIBRARY})
|
||||||
|
|
||||||
target_link_libraries(${exe_name} config)
|
|
||||||
linkCoreLibraries(${exe_name})
|
linkCoreLibraries(${exe_name})
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
||||||
|
find_package(LibConfig REQUIRED)
|
||||||
|
|
|
@ -123,11 +123,12 @@ void manage_keys(char *keys_file)
|
||||||
{
|
{
|
||||||
const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
|
const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
|
||||||
uint8_t keys[KEYS_SIZE];
|
uint8_t keys[KEYS_SIZE];
|
||||||
|
struct stat existence;
|
||||||
/* TODO: stat the file before trying to open it. We aren't cave people! */
|
FILE *keysf;
|
||||||
FILE *keysf = fopen(keys_file, "r");
|
|
||||||
if (keysf != NULL) {
|
/* Check if file exits, proceed to open and load keys */
|
||||||
/* if file was opened successfully -- 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);
|
size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keysf);
|
||||||
if (read_size != KEYS_SIZE) {
|
if (read_size != KEYS_SIZE) {
|
||||||
printf("Error while reading the key file\nExiting.\n");
|
printf("Error while reading the key file\nExiting.\n");
|
||||||
|
|
|
@ -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)
|
|
@ -6,11 +6,15 @@ port = 33445;
|
||||||
// The key file
|
// The key file
|
||||||
// make sure that the user who runs the server
|
// make sure that the user who runs the server
|
||||||
// does have permissions to read it/write to it
|
// 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"
|
keys_file = "/home/tom/.bootstrap_server.keys"
|
||||||
|
|
||||||
// The PID file written to by bootstrap_server,
|
// The PID file written to by bootstrap_server,
|
||||||
// make sure that the user who runs the server
|
// make sure that the user who runs the server
|
||||||
// does have permissions to write to it
|
// 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";
|
pid_file = "/home/tom/.bootstrap_server.pid";
|
||||||
|
|
||||||
// The info of the node bootstap_server will
|
// The info of the node bootstap_server will
|
||||||
|
|
|
@ -4,6 +4,7 @@ project(DHT_bootstrap C)
|
||||||
set(exe_name DHT_bootstrap)
|
set(exe_name DHT_bootstrap)
|
||||||
|
|
||||||
add_executable(${exe_name}
|
add_executable(${exe_name}
|
||||||
DHT_bootstrap.c ../testing/misc_tools.c)
|
DHT_bootstrap.c
|
||||||
|
../testing/misc_tools.c)
|
||||||
|
|
||||||
linkCoreLibraries(${exe_name})
|
linkCoreLibraries(${exe_name})
|
||||||
|
|
40
start_guide.de.md
Normal file
40
start_guide.de.md
Normal 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
38
start_guide.md
Normal 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.
|
|
@ -11,8 +11,8 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Messenger_test.cmake)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nTox_win32.cmake)
|
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nTox_win32.cmake)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nTox.cmake)
|
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nTox.cmake)
|
||||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/toxic.cmake)
|
add_subdirectory(toxic)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -186,7 +186,7 @@ int main(int argc, char *argv[])
|
||||||
fclose(file2);
|
fclose(file2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* if buffer is empty and the connection timed out. */
|
/* if buffer is empty and the connection timed out. */
|
||||||
else if(is_cryptoconnected(inconnection) == 4) {
|
else if(is_cryptoconnected(inconnection) == 4) {
|
||||||
crypto_kill(inconnection);
|
crypto_kill(inconnection);
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ int main(int argc, char *argv[])
|
||||||
fclose(file2);
|
fclose(file2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* if buffer is empty and the connection timed out. */
|
/* if buffer is empty and the connection timed out. */
|
||||||
else if(is_cryptoconnected(connection) == 4) {
|
else if(is_cryptoconnected(connection) == 4) {
|
||||||
crypto_kill(connection);
|
crypto_kill(connection);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ void print_friendlist()
|
||||||
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(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]);
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,9 @@ 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");
|
||||||
scanf("%s", temp_id);
|
if(scanf("%s", temp_id) != 1)
|
||||||
|
exit(0);
|
||||||
|
|
||||||
DHT_addfriend(hex_string_to_bin(temp_id));
|
DHT_addfriend(hex_string_to_bin(temp_id));
|
||||||
|
|
||||||
/* initialize networking */
|
/* initialize networking */
|
||||||
|
|
|
@ -211,4 +211,4 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,4 +198,4 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ project(DHT_cryptosendfiletest C)
|
||||||
set(exe_name DHT_cryptosendfiletest)
|
set(exe_name DHT_cryptosendfiletest)
|
||||||
|
|
||||||
add_executable(${exe_name}
|
add_executable(${exe_name}
|
||||||
DHT_cryptosendfiletest.c misc_tools.c)
|
DHT_cryptosendfiletest.c
|
||||||
|
misc_tools.c)
|
||||||
|
|
||||||
linkCoreLibraries(${exe_name})
|
linkCoreLibraries(${exe_name})
|
||||||
|
|
|
@ -4,6 +4,6 @@ project(DHT_sendfiletest C)
|
||||||
set(exe_name DHT_sendfiletest)
|
set(exe_name DHT_sendfiletest)
|
||||||
|
|
||||||
add_executable(${exe_name}
|
add_executable(${exe_name}
|
||||||
DHT_sendfiletest.c)
|
DHT_sendfiletest.c)
|
||||||
|
|
||||||
linkCoreLibraries(${exe_name})
|
linkCoreLibraries(${exe_name})
|
||||||
|
|
|
@ -4,6 +4,7 @@ project(DHT_test C)
|
||||||
set(exe_name DHT_test)
|
set(exe_name DHT_test)
|
||||||
|
|
||||||
add_executable(${exe_name}
|
add_executable(${exe_name}
|
||||||
DHT_test.c misc_tools.c)
|
DHT_test.c
|
||||||
|
misc_tools.c)
|
||||||
|
|
||||||
linkCoreLibraries(${exe_name})
|
linkCoreLibraries(${exe_name})
|
||||||
|
|
|
@ -4,6 +4,6 @@ project(Lossless_UDP_testclient C)
|
||||||
set(exe_name Lossless_UDP_testclient)
|
set(exe_name Lossless_UDP_testclient)
|
||||||
|
|
||||||
add_executable(${exe_name}
|
add_executable(${exe_name}
|
||||||
Lossless_UDP_testclient.c)
|
Lossless_UDP_testclient.c)
|
||||||
|
|
||||||
linkCoreLibraries(${exe_name})
|
linkCoreLibraries(${exe_name})
|
||||||
|
|
|
@ -4,6 +4,6 @@ project(Lossless_UDP_testserver C)
|
||||||
set(exe_name Lossless_UDP_testserver)
|
set(exe_name Lossless_UDP_testserver)
|
||||||
|
|
||||||
add_executable(${exe_name}
|
add_executable(${exe_name}
|
||||||
Lossless_UDP_testserver.c)
|
Lossless_UDP_testserver.c)
|
||||||
|
|
||||||
linkCoreLibraries(${exe_name})
|
linkCoreLibraries(${exe_name})
|
||||||
|
|
|
@ -4,6 +4,6 @@ project(Messenger_test C)
|
||||||
set(exe_name Messenger_test)
|
set(exe_name Messenger_test)
|
||||||
|
|
||||||
add_executable(${exe_name}
|
add_executable(${exe_name}
|
||||||
Messenger_test.c misc_tools.c)
|
Messenger_test.c misc_tools.c)
|
||||||
|
|
||||||
linkCoreLibraries(${exe_name})
|
linkCoreLibraries(${exe_name})
|
||||||
|
|
|
@ -4,8 +4,9 @@ project(nTox C)
|
||||||
set(exe_name nTox)
|
set(exe_name nTox)
|
||||||
|
|
||||||
add_executable(${exe_name}
|
add_executable(${exe_name}
|
||||||
nTox.c misc_tools.c)
|
nTox.c misc_tools.c)
|
||||||
|
|
||||||
target_link_libraries(${exe_name} ncurses)
|
target_link_libraries(${exe_name}
|
||||||
|
ncurses)
|
||||||
|
|
||||||
linkCoreLibraries(${exe_name})
|
linkCoreLibraries(${exe_name})
|
||||||
|
|
|
@ -26,4 +26,4 @@
|
||||||
|
|
||||||
unsigned char * hex_string_to_bin(char hex_string[]);
|
unsigned char * hex_string_to_bin(char hex_string[]);
|
||||||
|
|
||||||
#endif // MISC_TOOLS_H
|
#endif // MISC_TOOLS_H
|
||||||
|
|
211
testing/nTox.c
211
testing/nTox.c
|
@ -20,12 +20,12 @@
|
||||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nTox.h"
|
#include "nTox.h"
|
||||||
#include "misc_tools.h"
|
#include "misc_tools.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#define c_sleep(x) Sleep(1*x)
|
#define c_sleep(x) Sleep(1*x)
|
||||||
#else
|
#else
|
||||||
|
@ -35,31 +35,75 @@
|
||||||
|
|
||||||
char lines[HISTORY][STRING_LENGTH];
|
char lines[HISTORY][STRING_LENGTH];
|
||||||
char line[STRING_LENGTH];
|
char line[STRING_LENGTH];
|
||||||
int x,y;
|
|
||||||
|
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 pending_requests[256][CLIENT_ID_SIZE];
|
||||||
uint8_t num_requests;
|
uint8_t num_requests = 0;
|
||||||
|
|
||||||
void new_lines(char *line)
|
void new_lines(char *line)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = HISTORY-1; i > 0; i--)
|
for (i = HISTORY-1; i > 0; i--)
|
||||||
strcpy(lines[i],lines[i-1]);
|
strcpy(lines[i], lines[i-1]);
|
||||||
|
|
||||||
strcpy(lines[0],line);
|
strcpy(lines[0], line);
|
||||||
do_refresh();
|
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)
|
void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
|
||||||
{
|
{
|
||||||
if (line[0] == '/') {
|
if (line[0] == '/') {
|
||||||
char command[STRING_LENGTH + 2] = "> ";
|
char inpt_command = line[1];
|
||||||
strcat(command, line);
|
char prompt[STRING_LENGTH + 2] = "> ";
|
||||||
new_lines(command);
|
strcat(prompt, line);
|
||||||
if (line[1] == 'f') { // add friend command: /f ID
|
new_lines(prompt);
|
||||||
|
if (inpt_command == 'f') { // add friend command: /f ID
|
||||||
int i;
|
int i;
|
||||||
char temp_id[128];
|
char temp_id[128];
|
||||||
for (i=0; i<128; i++)
|
for (i = 0; i < 128; i++)
|
||||||
temp_id[i] = line[i+3];
|
temp_id[i] = line[i+3];
|
||||||
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"));
|
||||||
char numstring[100];
|
char numstring[100];
|
||||||
|
@ -67,82 +111,121 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
|
||||||
new_lines(numstring);
|
new_lines(numstring);
|
||||||
do_refresh();
|
do_refresh();
|
||||||
}
|
}
|
||||||
else if (line[1] == 'd') {
|
else if (inpt_command == 'd') {
|
||||||
doMessenger();
|
doMessenger();
|
||||||
}
|
}
|
||||||
else if (line[1] == 'm') { //message command: /m friendnumber messsage
|
else if (inpt_command == 'm') { //message command: /m friendnumber messsage
|
||||||
int i;
|
|
||||||
size_t 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++) {
|
int i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
if (line[i+3] != ' ') {
|
if (line[i+3] != ' ') {
|
||||||
numstring[i] = line[i+3];
|
numstring[i] = line[i+3];
|
||||||
} else {
|
} else {
|
||||||
int j;
|
int j;
|
||||||
for (j=i+1; j<len; j++)
|
for (j = (i+1); j < len; j++)
|
||||||
message[j-i-1] = line[j+3];
|
message[j-i-1] = line[j+3];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int num = atoi(numstring);
|
int num = atoi(numstring);
|
||||||
if(m_sendmessage(num, (uint8_t*) message, sizeof(message)) != 1) {
|
if (m_sendmessage(num, (uint8_t*) message, sizeof(message)) != 1) {
|
||||||
new_lines("[i] could not send message");
|
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];
|
uint8_t name[MAX_NAME_LENGTH];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t len = strlen(line);
|
size_t len = strlen(line);
|
||||||
for (i=3; i<len; i++) {
|
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];
|
||||||
}
|
}
|
||||||
name[i - 3] = 0;
|
name[i-3] = 0;
|
||||||
setname(name, i);
|
setname(name, i);
|
||||||
char numstring[100];
|
char numstring[100];
|
||||||
sprintf(numstring, "[i] changed nick to %s", (char*)name);
|
sprintf(numstring, "[i] changed nick to %s", (char*)name);
|
||||||
new_lines(numstring);
|
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];
|
uint8_t status[MAX_USERSTATUS_LENGTH];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t len = strlen(line);
|
size_t len = strlen(line);
|
||||||
for (i=3; i<len; i++) {
|
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];
|
||||||
}
|
}
|
||||||
status[i - 3] = 0;
|
status[i-3] = 0;
|
||||||
m_set_userstatus(status, strlen((char*)status));
|
m_set_userstatus(status, strlen((char*)status));
|
||||||
char numstring[100];
|
char numstring[100];
|
||||||
sprintf(numstring, "[i] changed status to %s", (char*)status);
|
sprintf(numstring, "[i] changed status to %s", (char*)status);
|
||||||
new_lines(numstring);
|
new_lines(numstring);
|
||||||
}
|
}
|
||||||
else if (line[1] == 'a') {
|
else if (inpt_command == 'a') {
|
||||||
uint8_t numf = atoi(line + 3);
|
uint8_t numf = atoi(line + 3);
|
||||||
char numchar[100];
|
char numchar[100];
|
||||||
sprintf(numchar, "[i] friend request %u accepted", numf);
|
|
||||||
new_lines(numchar);
|
|
||||||
int num = m_addfriend_norequest(pending_requests[numf]);
|
int num = m_addfriend_norequest(pending_requests[numf]);
|
||||||
sprintf(numchar, "[i] added friendnumber %d", num);
|
if (num != -1) {
|
||||||
new_lines(numchar);
|
sprintf(numchar, "[i] friend request %u accepted", numf);
|
||||||
|
new_lines(numchar);
|
||||||
|
sprintf(numchar, "[i] added friendnumber %d", num);
|
||||||
|
new_lines(numchar);
|
||||||
|
} else {
|
||||||
|
sprintf(numchar, "[i] failed to add friend");
|
||||||
|
new_lines(numchar);
|
||||||
|
}
|
||||||
do_refresh();
|
do_refresh();
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (line[1] == 'q') { //exit
|
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();
|
endwin();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
|
} else {
|
||||||
|
new_lines("[i] invalid command");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
new_lines("[i] invalid command");
|
||||||
//new_lines(line);
|
//new_lines(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrap(char output[STRING_LENGTH], char input[STRING_LENGTH], int line_width)
|
void wrap(char output[STRING_LENGTH], char input[STRING_LENGTH], int line_width)
|
||||||
{
|
{
|
||||||
int i = 0;
|
|
||||||
strcpy(output,input);
|
strcpy(output,input);
|
||||||
size_t len = strlen(output);
|
size_t len = strlen(output);
|
||||||
|
int i = 0;
|
||||||
for (i = line_width; i < len; i = i + line_width) {
|
for (i = line_width; i < len; i = i + line_width) {
|
||||||
while (output[i] != ' ' && i != 0) {
|
while (output[i] != ' ' && i != 0) {
|
||||||
i--;
|
i--;
|
||||||
|
@ -156,9 +239,9 @@ void wrap(char output[STRING_LENGTH], char input[STRING_LENGTH], int line_width)
|
||||||
int count_lines(char *string)
|
int count_lines(char *string)
|
||||||
{
|
{
|
||||||
size_t len = strlen(string);
|
size_t len = strlen(string);
|
||||||
int i;
|
|
||||||
int count = 1;
|
int count = 1;
|
||||||
for (i=0; i < len; i++) {
|
int i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
if (string[i] == '\n')
|
if (string[i] == '\n')
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +252,7 @@ char *appender(char *str, const char c)
|
||||||
{
|
{
|
||||||
size_t 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;
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
|
@ -177,21 +260,21 @@ char *appender(char *str, const char c)
|
||||||
|
|
||||||
void do_refresh()
|
void do_refresh()
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int count=0;
|
int count=0;
|
||||||
int l;
|
|
||||||
char wrap_output[STRING_LENGTH];
|
char wrap_output[STRING_LENGTH];
|
||||||
for (i=0; i<HISTORY; i++) {
|
int L;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < HISTORY; i++) {
|
||||||
wrap(wrap_output, lines[i], x);
|
wrap(wrap_output, lines[i], x);
|
||||||
l = count_lines(wrap_output);
|
L = count_lines(wrap_output);
|
||||||
count = count + l;
|
count = count + L;
|
||||||
if (count < y) {
|
if (count < y) {
|
||||||
move(y-1-count,0);
|
move(y-1-count, 0);
|
||||||
printw(wrap_output);
|
printw(wrap_output);
|
||||||
clrtoeol();
|
clrtoeol();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
move(y-1,0);
|
move(y-1, 0);
|
||||||
clrtoeol();
|
clrtoeol();
|
||||||
printw(">> ");
|
printw(">> ");
|
||||||
printw(line);
|
printw(line);
|
||||||
|
@ -222,12 +305,13 @@ void print_message(int friendnumber, uint8_t * string, uint16_t length)
|
||||||
timeinfo = localtime ( &rawtime );
|
timeinfo = localtime ( &rawtime );
|
||||||
char* temp = asctime(timeinfo);
|
char* temp = asctime(timeinfo);
|
||||||
size_t 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); // timestamp
|
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];
|
char name[MAX_NAME_LENGTH];
|
||||||
getname(friendnumber, (uint8_t*)name);
|
getname(friendnumber, (uint8_t*)name);
|
||||||
char msg[100+length];
|
char msg[100+length];
|
||||||
|
@ -235,7 +319,8 @@ void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) {
|
||||||
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);
|
||||||
char msg[100+length+strlen(name)+1];
|
char msg[100+length+strlen(name)+1];
|
||||||
|
@ -243,15 +328,17 @@ void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) {
|
||||||
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"))) {
|
data_file = fopen("data","r");
|
||||||
|
if (data_file) {
|
||||||
//load keys
|
//load keys
|
||||||
fseek(data_file, 0, SEEK_END);
|
fseek(data_file, 0, SEEK_END);
|
||||||
int size = ftell(data_file);
|
int size = ftell(data_file);
|
||||||
fseek(data_file, 0, SEEK_SET);
|
fseek(data_file, 0, SEEK_SET);
|
||||||
uint8_t data[size];
|
uint8_t data[size];
|
||||||
if(fread(data, sizeof(uint8_t), size, data_file) != size){
|
if (fread(data, sizeof(uint8_t), size, data_file) != size){
|
||||||
printf("[i] could not read data file\n[i] exiting\n");
|
printf("[i] could not read data file\n[i] exiting\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -262,7 +349,7 @@ void load_key(){
|
||||||
uint8_t data[size];
|
uint8_t data[size];
|
||||||
Messenger_save(data);
|
Messenger_save(data);
|
||||||
data_file = fopen("data","w");
|
data_file = fopen("data","w");
|
||||||
if(fwrite(data, sizeof(uint8_t), size, data_file) != size){
|
if (fwrite(data, sizeof(uint8_t), size, data_file) != size){
|
||||||
printf("[i] could not write data file\n[i] exiting\n");
|
printf("[i] could not write data file\n[i] exiting\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -292,28 +379,29 @@ int main(int argc, char *argv[])
|
||||||
m_callback_namechange(print_nickchange);
|
m_callback_namechange(print_nickchange);
|
||||||
m_callback_userstatus(print_statuschange);
|
m_callback_userstatus(print_statuschange);
|
||||||
char idstring0[200];
|
char idstring0[200];
|
||||||
char idstring1[32][5];
|
char idstring1[PUB_KEY_BYTES][5];
|
||||||
char idstring2[32][5];
|
char idstring2[PUB_KEY_BYTES][5];
|
||||||
uint32_t i;
|
int i;
|
||||||
for(i = 0; i < 32; 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");
|
strcpy(idstring1[i],"0");
|
||||||
else
|
else
|
||||||
strcpy(idstring1[i], "");
|
strcpy(idstring1[i], "");
|
||||||
sprintf(idstring2[i], "%hhX",self_public_key[i]);
|
sprintf(idstring2[i], "%hhX",self_public_key[i]);
|
||||||
}
|
}
|
||||||
strcpy(idstring0,"[i] your ID: ");
|
strcpy(idstring0,"[i] your ID: ");
|
||||||
for (i=0; i<32; i++) {
|
int j;
|
||||||
strcat(idstring0,idstring1[i]);
|
for (j = 0; j < PUB_KEY_BYTES; j++) {
|
||||||
strcat(idstring0,idstring2[i]);
|
strcat(idstring0,idstring1[j]);
|
||||||
|
strcat(idstring0,idstring2[j]);
|
||||||
}
|
}
|
||||||
initscr();
|
initscr();
|
||||||
noecho();
|
noecho();
|
||||||
raw();
|
raw();
|
||||||
getmaxyx(stdscr,y,x);
|
getmaxyx(stdscr, y, x);
|
||||||
new_lines(idstring0);
|
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, "");
|
strcpy(line, "");
|
||||||
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]));
|
||||||
|
@ -336,7 +424,6 @@ int main(int argc, char *argv[])
|
||||||
do_refresh();
|
do_refresh();
|
||||||
|
|
||||||
c = getch();
|
c = getch();
|
||||||
|
|
||||||
if (c == ERR || c == 27)
|
if (c == ERR || c == 27)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -345,7 +432,7 @@ int main(int argc, char *argv[])
|
||||||
line_eval(lines, line);
|
line_eval(lines, line);
|
||||||
strcpy(line, "");
|
strcpy(line, "");
|
||||||
} else if (c == 127) {
|
} else if (c == 127) {
|
||||||
line[strlen(line) - 1] = '\0';
|
line[strlen(line)-1] = '\0';
|
||||||
} else if (isalnum(c) || ispunct(c) || c == ' ') {
|
} else if (isalnum(c) || ispunct(c) || c == ' ') {
|
||||||
strcpy(line, appender(line, (char) c));
|
strcpy(line, appender(line, (char) c));
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "../core/network.h"
|
#include "../core/network.h"
|
||||||
#define STRING_LENGTH 256
|
#define STRING_LENGTH 256
|
||||||
#define HISTORY 50
|
#define HISTORY 50
|
||||||
|
#define PUB_KEY_BYTES 32
|
||||||
|
|
||||||
void new_lines(char *line);
|
void new_lines(char *line);
|
||||||
void line_eval(char lines[HISTORY][STRING_LENGTH], char *line);
|
void line_eval(char lines[HISTORY][STRING_LENGTH], char *line);
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
|
|
||||||
uint8_t pending_requests[256][CLIENT_ID_SIZE];
|
uint8_t pending_requests[256][CLIENT_ID_SIZE];
|
||||||
uint8_t num_requests;
|
uint8_t num_requests = 0;
|
||||||
|
|
||||||
char line[STRING_LENGTH];
|
char line[STRING_LENGTH];
|
||||||
char users_id[200];
|
char users_id[200];
|
||||||
|
@ -89,14 +89,13 @@ void print_statuschange(int friendnumber, uint8_t *string, uint16_t length)
|
||||||
void load_key()
|
void load_key()
|
||||||
{
|
{
|
||||||
FILE *data_file = NULL;
|
FILE *data_file = NULL;
|
||||||
|
data_file = fopen("data","r");
|
||||||
if ((data_file = fopen("data", "r"))) {
|
if (data_file) {
|
||||||
fseek(data_file, 0, SEEK_END);
|
fseek(data_file, 0, SEEK_END);
|
||||||
int size = ftell(data_file);
|
int size = ftell(data_file);
|
||||||
fseek(data_file, 0, SEEK_SET);
|
fseek(data_file, 0, SEEK_SET);
|
||||||
uint8_t data[size];
|
uint8_t data[size];
|
||||||
|
if (fread(data, sizeof(uint8_t), size, data_file) != size) {
|
||||||
if(fread(data, sizeof(uint8_t), size, data_file) != size) {
|
|
||||||
printf("\n[i] Could not read the data file. Exiting.");
|
printf("\n[i] Could not read the data file. Exiting.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -108,23 +107,23 @@ void load_key()
|
||||||
Messenger_save(data);
|
Messenger_save(data);
|
||||||
data_file = fopen("data", "w");
|
data_file = fopen("data", "w");
|
||||||
|
|
||||||
if(fwrite(data, sizeof(uint8_t), size, data_file) != size) {
|
if (fwrite(data, sizeof(uint8_t), size, data_file) != size) {
|
||||||
printf("\n[i] Could not write data to file. Exiting.");
|
printf("\n[i] Could not write data to file. Exiting.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(data_file);
|
fclose(data_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void line_eval(char* line)
|
void line_eval(char* line)
|
||||||
{
|
{
|
||||||
if(line[0] == '/') {
|
if(line[0] == '/') {
|
||||||
|
char inpt_command = line[1];
|
||||||
/* Add friend */
|
/* Add friend */
|
||||||
if(line[1] == 'f') {
|
if(inpt_command == 'f') {
|
||||||
int i;
|
int i;
|
||||||
char temp_id[128];
|
char temp_id[128];
|
||||||
for (i=0; i<128; i++)
|
for (i = 0; i < 128; i++)
|
||||||
temp_id[i] = line[i+3];
|
temp_id[i] = line[i+3];
|
||||||
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"));
|
||||||
char numstring[100];
|
char numstring[100];
|
||||||
|
@ -132,17 +131,16 @@ void line_eval(char* line)
|
||||||
printf(numstring);
|
printf(numstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (line[1] == 'r') {
|
else if (inpt_command == 'r') {
|
||||||
do_header();
|
do_header();
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (line[1] == 'l') {
|
else if (inpt_command == 'l') {
|
||||||
printf("\n[i] Friend List | Total: %d\n\n", getnumfriends());
|
printf("\n[i] Friend List | Total: %d\n\n", getnumfriends());
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
for (i = 0; i < getnumfriends(); i++) {
|
||||||
for (i=0; i < getnumfriends(); i++) {
|
|
||||||
char name[MAX_NAME_LENGTH];
|
char name[MAX_NAME_LENGTH];
|
||||||
getname(i, (uint8_t*)name);
|
getname(i, (uint8_t*)name);
|
||||||
if (m_friendstatus(i) == 0)
|
if (m_friendstatus(i) == 0)
|
||||||
|
@ -152,11 +150,11 @@ void line_eval(char* line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (line[1] == 'd') {
|
else if (inpt_command == 'd') {
|
||||||
size_t len = strlen(line);
|
size_t len = strlen(line);
|
||||||
char numstring[len-3];
|
char numstring[len-3];
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (line[i+3] != ' ') {
|
if (line[i+3] != ' ') {
|
||||||
numstring[i] = line[i+3];
|
numstring[i] = line[i+3];
|
||||||
}
|
}
|
||||||
|
@ -166,17 +164,17 @@ void line_eval(char* line)
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
}
|
}
|
||||||
/* Send message to friend */
|
/* Send message to friend */
|
||||||
else if (line[1] == 'm') {
|
else if (inpt_command == 'm') {
|
||||||
int i;
|
|
||||||
size_t 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++) {
|
int i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
if (line[i+3] != ' ') {
|
if (line[i+3] != ' ') {
|
||||||
numstring[i] = line[i+3];
|
numstring[i] = line[i+3];
|
||||||
} else {
|
} else {
|
||||||
int j;
|
int j;
|
||||||
for (j=i+1; j<len; j++)
|
for (j = (i+1); j < len; j++)
|
||||||
message[j-i-1] = line[j+3];
|
message[j-i-1] = line[j+3];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -190,37 +188,37 @@ void line_eval(char* line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (line[1] == 'n') {
|
else if (inpt_command == 'n') {
|
||||||
uint8_t name[MAX_NAME_LENGTH];
|
uint8_t name[MAX_NAME_LENGTH];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t len = strlen(line);
|
size_t len = strlen(line);
|
||||||
for (i=3; i<len; i++) {
|
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];
|
||||||
}
|
}
|
||||||
name[i - 3] = 0;
|
name[i-3] = 0;
|
||||||
setname(name, i);
|
setname(name, i);
|
||||||
char numstring[100];
|
char numstring[100];
|
||||||
sprintf(numstring, "\n[i] changed nick to %s\n\n", (char*)name);
|
sprintf(numstring, "\n[i] changed nick to %s\n\n", (char*)name);
|
||||||
printf(numstring);
|
printf(numstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (line[1] == 's') {
|
else if (inpt_command == 's') {
|
||||||
uint8_t status[MAX_USERSTATUS_LENGTH];
|
uint8_t status[MAX_USERSTATUS_LENGTH];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t len = strlen(line);
|
size_t len = strlen(line);
|
||||||
for (i=3; i<len; i++) {
|
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];
|
||||||
}
|
}
|
||||||
status[i - 3] = 0;
|
status[i-3] = 0;
|
||||||
m_set_userstatus(status, strlen((char*)status));
|
m_set_userstatus(status, strlen((char*)status));
|
||||||
char numstring[100];
|
char numstring[100];
|
||||||
sprintf(numstring, "\n[i] changed status to %s\n\n", (char*)status);
|
sprintf(numstring, "\n[i] changed status to %s\n\n", (char*)status);
|
||||||
printf(numstring);
|
printf(numstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (line[1] == 'a') {
|
else if (inpt_command == 'a') {
|
||||||
uint8_t numf = atoi(line + 3);
|
uint8_t numf = atoi(line + 3);
|
||||||
char numchar[100];
|
char numchar[100];
|
||||||
sprintf(numchar, "\n[i] friend request %u accepted\n\n", numf);
|
sprintf(numchar, "\n[i] friend request %u accepted\n\n", numf);
|
||||||
|
@ -230,12 +228,10 @@ void line_eval(char* line)
|
||||||
printf(numchar);
|
printf(numchar);
|
||||||
}
|
}
|
||||||
/* EXIT */
|
/* EXIT */
|
||||||
else if (line[1] == 'q') {
|
else if (inpt_command == 'q') {
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
else {
|
|
||||||
//nothing atm
|
//nothing atm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,12 +251,10 @@ int main(int argc, char *argv[])
|
||||||
printf("[!] Usage: %s [IP] [port] [public_key] <nokey>\n", argv[0]);
|
printf("[!] Usage: %s [IP] [port] [public_key] <nokey>\n", argv[0]);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (initMessenger() == -1) {
|
if (initMessenger() == -1) {
|
||||||
printf("initMessenger failed");
|
printf("initMessenger failed");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc > 4) {
|
if (argc > 4) {
|
||||||
if(strncmp(argv[4], "nokey", 6) < 0) {
|
if(strncmp(argv[4], "nokey", 6) < 0) {
|
||||||
}
|
}
|
||||||
|
@ -272,26 +266,25 @@ int main(int argc, char *argv[])
|
||||||
m_callback_friendmessage(print_message);
|
m_callback_friendmessage(print_message);
|
||||||
m_callback_namechange(print_nickchange);
|
m_callback_namechange(print_nickchange);
|
||||||
m_callback_userstatus(print_statuschange);
|
m_callback_userstatus(print_statuschange);
|
||||||
|
char idstring1[PUB_KEY_BYTES][5];
|
||||||
char idstring1[32][5];
|
char idstring2[PUB_KEY_BYTES][5];
|
||||||
char idstring2[32][5];
|
int i;
|
||||||
uint32_t i;
|
for(i = 0; i < PUB_KEY_BYTES; i++)
|
||||||
for(i = 0; i < 32; i++)
|
|
||||||
{
|
{
|
||||||
if(self_public_key[i] < 16)
|
if(self_public_key[i] < (PUB_KEY_BYTES/2))
|
||||||
strcpy(idstring1[i],"0");
|
strcpy(idstring1[i],"0");
|
||||||
else
|
else
|
||||||
strcpy(idstring1[i], "");
|
strcpy(idstring1[i], "");
|
||||||
sprintf(idstring2[i], "%hhX",self_public_key[i]);
|
sprintf(idstring2[i], "%hhX",self_public_key[i]);
|
||||||
}
|
}
|
||||||
strcpy(users_id,"[i] your ID: ");
|
strcpy(users_id,"[i] your ID: ");
|
||||||
for (i=0; i<32; i++) {
|
int j;
|
||||||
strcat(users_id,idstring1[i]);
|
for (j = 0; j < PUB_KEY_BYTES; j++) {
|
||||||
strcat(users_id,idstring2[i]);
|
strcat(users_id,idstring1[j]);
|
||||||
|
strcat(users_id,idstring2[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
do_header();
|
do_header();
|
||||||
|
|
||||||
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]));
|
||||||
int resolved_address = resolve_addr(argv[1]);
|
int resolved_address = resolve_addr(argv[1]);
|
||||||
|
@ -301,12 +294,9 @@ int main(int argc, char *argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3]));
|
DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3]));
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
int on = 0;
|
int on = 0;
|
||||||
|
|
||||||
_beginthread(get_input, 0, NULL);
|
_beginthread(get_input, 0, NULL);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if (on == 1 && DHT_isconnected() == -1) {
|
if (on == 1 && DHT_isconnected() == -1) {
|
||||||
printf("\n---------------------------------");
|
printf("\n---------------------------------");
|
||||||
|
@ -314,16 +304,13 @@ int main(int argc, char *argv[])
|
||||||
printf("\n---------------------------------\n\n");
|
printf("\n---------------------------------\n\n");
|
||||||
on = 0;
|
on = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (on == 0 && DHT_isconnected()) {
|
if (on == 0 && DHT_isconnected()) {
|
||||||
printf("\n[i] Connected to DHT");
|
printf("\n[i] Connected to DHT");
|
||||||
printf("\n---------------------------------\n\n");
|
printf("\n---------------------------------\n\n");
|
||||||
on = 1;
|
on = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
doMessenger();
|
doMessenger();
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -27,6 +27,7 @@
|
||||||
#include "../core/network.h"
|
#include "../core/network.h"
|
||||||
|
|
||||||
#define STRING_LENGTH 256
|
#define STRING_LENGTH 256
|
||||||
|
#define PUB_KEY_BYTES 32
|
||||||
|
|
||||||
void do_header();
|
void do_header();
|
||||||
void print_message(int friendnumber, uint8_t * string, uint16_t length);
|
void print_message(int friendnumber, uint8_t * string, uint16_t length);
|
||||||
|
|
|
@ -4,8 +4,12 @@ project(toxic C)
|
||||||
set(exe_name toxic)
|
set(exe_name toxic)
|
||||||
|
|
||||||
add_executable(${exe_name}
|
add_executable(${exe_name}
|
||||||
toxic/main.c toxic/prompt.c)
|
main.c
|
||||||
|
prompt.c
|
||||||
target_link_libraries(${exe_name} curses)
|
friendlist.c
|
||||||
|
chat.c)
|
||||||
|
|
||||||
|
target_link_libraries(${exe_name}
|
||||||
|
curses)
|
||||||
|
|
||||||
linkCoreLibraries(${exe_name})
|
linkCoreLibraries(${exe_name})
|
155
testing/toxic/chat.c
Normal file
155
testing/toxic/chat.c
Normal 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
166
testing/toxic/friendlist.c
Normal 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;
|
||||||
|
}
|
|
@ -14,6 +14,10 @@
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
|
|
||||||
extern ToxWindow new_prompt();
|
extern ToxWindow new_prompt();
|
||||||
|
extern ToxWindow new_friendlist();
|
||||||
|
|
||||||
|
extern int friendlist_onFriendAdded(int num);
|
||||||
|
|
||||||
extern int add_req(uint8_t* public_key); // XXX
|
extern int add_req(uint8_t* public_key); // XXX
|
||||||
|
|
||||||
#define TOXWINDOWS_MAX_NUM 32
|
#define TOXWINDOWS_MAX_NUM 32
|
||||||
|
@ -25,21 +29,59 @@ static ToxWindow* prompt;
|
||||||
|
|
||||||
// CALLBACKS START
|
// CALLBACKS START
|
||||||
void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) {
|
void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) {
|
||||||
|
size_t i;
|
||||||
int n = add_req(public_key);
|
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) {
|
void on_message(int friendnumber, uint8_t* string, uint16_t length) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
wprintw(prompt->window, "\n(message) %d: %s!\n", friendnumber, string);
|
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) {
|
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) {
|
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
|
// CALLBACKS END
|
||||||
|
|
||||||
|
@ -73,7 +115,7 @@ static void init_tox() {
|
||||||
m_callback_userstatus(on_statuschange);
|
m_callback_userstatus(on_statuschange);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_window(ToxWindow w) {
|
int add_window(ToxWindow w) {
|
||||||
if(w_num == TOXWINDOWS_MAX_NUM)
|
if(w_num == TOXWINDOWS_MAX_NUM)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -88,14 +130,22 @@ static int add_window(ToxWindow w) {
|
||||||
windows[w_num++] = w;
|
windows[w_num++] = w;
|
||||||
w.onInit(&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() {
|
static void init_windows() {
|
||||||
w_num = 0;
|
w_num = 0;
|
||||||
w_active = 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");
|
fprintf(stderr, "add_window() failed.\n");
|
||||||
|
|
||||||
endwin();
|
endwin();
|
||||||
|
@ -134,14 +184,18 @@ static void load_data() {
|
||||||
|
|
||||||
if(buf == NULL) {
|
if(buf == NULL) {
|
||||||
fprintf(stderr, "malloc() failed.\n");
|
fprintf(stderr, "malloc() failed.\n");
|
||||||
|
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
|
endwin();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fread(buf, len, 1, fd) != 1){
|
if(fread(buf, len, 1, fd) != 1){
|
||||||
fprintf(stderr, "fread() failed.\n");
|
fprintf(stderr, "fread() failed.\n");
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
|
endwin();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +207,7 @@ static void load_data() {
|
||||||
|
|
||||||
if(buf == NULL) {
|
if(buf == NULL) {
|
||||||
fprintf(stderr, "malloc() failed.\n");
|
fprintf(stderr, "malloc() failed.\n");
|
||||||
|
endwin();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,14 +216,18 @@ static void load_data() {
|
||||||
fd = fopen("data", "w");
|
fd = fopen("data", "w");
|
||||||
if(fd == NULL) {
|
if(fd == NULL) {
|
||||||
fprintf(stderr, "fopen() failed.\n");
|
fprintf(stderr, "fopen() failed.\n");
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
|
endwin();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fwrite(buf, len, 1, fd) != 1){
|
if(fwrite(buf, len, 1, fd) != 1){
|
||||||
fprintf(stderr, "fwrite() failed.\n");
|
fprintf(stderr, "fwrite() failed.\n");
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
|
endwin();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,6 +237,7 @@ static void load_data() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_bar() {
|
static void draw_bar() {
|
||||||
|
static int odd = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
attron(COLOR_PAIR(4));
|
attron(COLOR_PAIR(4));
|
||||||
|
@ -186,12 +246,26 @@ static void draw_bar() {
|
||||||
|
|
||||||
move(LINES - 1, 0);
|
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++) {
|
for(i=0; i<w_num; i++) {
|
||||||
if(i == w_active) {
|
if(i == w_active) {
|
||||||
attron(A_BOLD);
|
attron(A_BOLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
printw(" %s ", windows[i].title);
|
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) {
|
if(i == w_active) {
|
||||||
attroff(A_BOLD);
|
attroff(A_BOLD);
|
||||||
|
@ -201,6 +275,11 @@ static void draw_bar() {
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void prepare_window(WINDOW* w) {
|
||||||
|
mvwin(w, 0, 0);
|
||||||
|
wresize(w, LINES-2, COLS);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
int ch;
|
int ch;
|
||||||
ToxWindow* a;
|
ToxWindow* a;
|
||||||
|
@ -211,14 +290,22 @@ int main(int argc, char* argv[]) {
|
||||||
init_windows();
|
init_windows();
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
|
// Update tox.
|
||||||
do_tox();
|
do_tox();
|
||||||
|
|
||||||
|
// Draw.
|
||||||
a = &windows[w_active];
|
a = &windows[w_active];
|
||||||
|
prepare_window(a->window);
|
||||||
|
a->blink = false;
|
||||||
a->onDraw(a);
|
a->onDraw(a);
|
||||||
draw_bar();
|
draw_bar();
|
||||||
|
|
||||||
|
// Handle input.
|
||||||
ch = getch();
|
ch = getch();
|
||||||
if(ch != ERR) {
|
if(ch == '\t') {
|
||||||
|
w_active = (w_active + 1) % w_num;
|
||||||
|
}
|
||||||
|
else if(ch != ERR) {
|
||||||
a->onKey(a, ch);
|
a->onKey(a, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX
|
uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX
|
||||||
uint8_t num_requests=0; // XXX
|
uint8_t num_requests=0; // XXX
|
||||||
|
|
||||||
|
extern void on_friendadded(int friendnumber);
|
||||||
|
|
||||||
// XXX:
|
// XXX:
|
||||||
int add_req(uint8_t* public_key) {
|
int add_req(uint8_t* public_key) {
|
||||||
memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE);
|
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) {
|
static void execute(ToxWindow* self, char* cmd) {
|
||||||
|
|
||||||
// quit/exit: Exit program.
|
if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) {
|
||||||
if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit")) {
|
|
||||||
endwin();
|
endwin();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -53,33 +54,32 @@ static void execute(ToxWindow* self, char* cmd) {
|
||||||
|
|
||||||
ip = strchr(cmd, ' ');
|
ip = strchr(cmd, ' ');
|
||||||
if(ip == NULL) {
|
if(ip == NULL) {
|
||||||
|
wprintw(self->window, "Invalid syntax.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ip++;
|
ip++;
|
||||||
|
|
||||||
port = strchr(ip, ' ');
|
port = strchr(ip, ' ');
|
||||||
if(port == NULL) {
|
if(port == NULL) {
|
||||||
|
wprintw(self->window, "Invalid syntax.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
port[0] = 0;
|
port[0] = 0;
|
||||||
port++;
|
port++;
|
||||||
|
|
||||||
key = strchr(port, ' ');
|
key = strchr(port, ' ');
|
||||||
if(key == NULL) {
|
if(key == NULL) {
|
||||||
|
wprintw(self->window, "Invalid syntax.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
key[0] = 0;
|
key[0] = 0;
|
||||||
key++;
|
key++;
|
||||||
|
|
||||||
if(atoi(port) == 0) {
|
if(atoi(port) == 0) {
|
||||||
|
wprintw(self->window, "Invalid syntax.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wprintw(self->window, "ip=%s, port=%s, key=%s\n", ip, port, key);
|
|
||||||
|
|
||||||
dht.port = htons(atoi(port));
|
dht.port = htons(atoi(port));
|
||||||
|
|
||||||
int resolved_address = resolve_addr(ip);
|
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));
|
DHT_bootstrap(dht, hex_string_to_bin(key));
|
||||||
}
|
}
|
||||||
else if(!strncmp(cmd, "add ", strlen("add "))) {
|
else if(!strncmp(cmd, "add ", strlen("add "))) {
|
||||||
|
uint8_t id_bin[32];
|
||||||
|
size_t i;
|
||||||
|
char xx[3];
|
||||||
|
uint32_t x;
|
||||||
|
|
||||||
char* id;
|
char* id;
|
||||||
char* msg;
|
char* msg;
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
id = strchr(cmd, ' ');
|
id = strchr(cmd, ' ');
|
||||||
|
|
||||||
if(id == NULL) {
|
if(id == NULL) {
|
||||||
|
wprintw(self->window, "Invalid syntax.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
id++;
|
id++;
|
||||||
|
|
||||||
msg = strchr(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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg[0] = 0;
|
for(i=0; i<32; i++) {
|
||||||
msg++;
|
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);
|
wprintw(self->window, "Friend added as %d.\n", num);
|
||||||
|
on_friendadded(num);
|
||||||
}
|
}
|
||||||
else if(!strncmp(cmd, "status ", strlen("status "))) {
|
else if(!strncmp(cmd, "status ", strlen("status "))) {
|
||||||
char* msg;
|
char* msg;
|
||||||
|
|
||||||
msg = strchr(cmd, ' ');
|
msg = strchr(cmd, ' ');
|
||||||
if(msg == NULL) {
|
if(msg == NULL) {
|
||||||
|
wprintw(self->window, "Invalid syntax.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg++;
|
msg++;
|
||||||
|
|
||||||
m_set_userstatus((uint8_t*) msg, strlen(msg)+1);
|
m_set_userstatus((uint8_t*) msg, strlen(msg)+1);
|
||||||
wprintw(self->window, "Status set to: %s.\n", msg);
|
wprintw(self->window, "Status set to: %s.\n", msg);
|
||||||
}
|
}
|
||||||
|
@ -133,33 +157,22 @@ static void execute(ToxWindow* self, char* cmd) {
|
||||||
if(nick == NULL) {
|
if(nick == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nick++;
|
nick++;
|
||||||
|
|
||||||
setname((uint8_t*) nick, strlen(nick)+1);
|
setname((uint8_t*) nick, strlen(nick)+1);
|
||||||
wprintw(self->window, "Nickname set to: %s.\n", nick);
|
wprintw(self->window, "Nickname set to: %s.\n", nick);
|
||||||
}
|
}
|
||||||
else if(!strcmp(cmd, "myid")) {
|
else if(!strcmp(cmd, "myid")) {
|
||||||
// XXX: Clean this up
|
char id[32*2 + 1] = {0};
|
||||||
char idstring0[200];
|
size_t i;
|
||||||
char idstring1[32][5];
|
|
||||||
char idstring2[32][5];
|
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
for(i = 0; i < 32; i++) {
|
for(i=0; i<32; i++) {
|
||||||
if(self_public_key[i] < 16)
|
char xx[3];
|
||||||
strcpy(idstring1[i], "0");
|
snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff);
|
||||||
else
|
strcat(id, xx);
|
||||||
strcpy(idstring1[i], "");
|
|
||||||
|
|
||||||
sprintf(idstring2[i], "%hhX", self_public_key[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<32; i++) {
|
wprintw(self->window, "%s\n", id);
|
||||||
strcat(idstring0, idstring1[i]);
|
|
||||||
strcat(idstring0, idstring2[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
wprintw(self->window, "%s\n", idstring0);
|
|
||||||
}
|
}
|
||||||
else if(!strncmp(cmd, "accept ", strlen("accept "))) {
|
else if(!strncmp(cmd, "accept ", strlen("accept "))) {
|
||||||
char* id;
|
char* id;
|
||||||
|
@ -167,17 +180,26 @@ static void execute(ToxWindow* self, char* cmd) {
|
||||||
|
|
||||||
id = strchr(cmd, ' ');
|
id = strchr(cmd, ' ');
|
||||||
if(id == NULL) {
|
if(id == NULL) {
|
||||||
|
wprintw(self->window, "Invalid syntax.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
id++;
|
id++;
|
||||||
|
|
||||||
num = atoi(id);
|
num = atoi(id);
|
||||||
if(num >= num_requests) {
|
if(num >= num_requests) {
|
||||||
|
wprintw(self->window, "Invalid syntax.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
num = m_addfriend_norequest(pending_requests[num]);
|
num = m_addfriend_norequest(pending_requests[num]);
|
||||||
wprintw(self->window, "Friend accepted as: %d.\n", 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 "))) {
|
else if(!strncmp(cmd, "msg ", strlen("msg "))) {
|
||||||
char* id;
|
char* id;
|
||||||
|
@ -186,26 +208,29 @@ static void execute(ToxWindow* self, char* cmd) {
|
||||||
id = strchr(cmd, ' ');
|
id = strchr(cmd, ' ');
|
||||||
|
|
||||||
if(id == NULL) {
|
if(id == NULL) {
|
||||||
|
wprintw(self->window, "Invalid syntax.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
id++;
|
id++;
|
||||||
|
|
||||||
msg = strchr(id, ' ');
|
msg = strchr(id, ' ');
|
||||||
if(msg == NULL) {
|
if(msg == NULL) {
|
||||||
|
wprintw(self->window, "Invalid syntax.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg[0] = 0;
|
msg[0] = 0;
|
||||||
msg++;
|
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");
|
wprintw(self->window, "Error occurred while sending message.\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wprintw(self->window, "Message successfully sent.\n");
|
wprintw(self->window, "Message successfully sent.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
wprintw(self->window, "Invalid syntax.\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prompt_onKey(ToxWindow* self, int key) {
|
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.
|
// BACKSPACE key: Remove one character from line.
|
||||||
else if(key == 0x107) {
|
else if(key == 0x107 || key == 0x8 || key == 0x7f) {
|
||||||
|
|
||||||
if(prompt_buf_pos != 0) {
|
if(prompt_buf_pos != 0) {
|
||||||
prompt_buf[--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) {
|
static void prompt_onDraw(ToxWindow* self) {
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
mvwin(self->window,0,0);
|
|
||||||
wresize(self->window, LINES-2, COLS);
|
|
||||||
|
|
||||||
getyx(self->window, y, x);
|
getyx(self->window, y, x);
|
||||||
(void) x;
|
(void) x;
|
||||||
|
|
||||||
|
@ -260,7 +282,7 @@ static void prompt_onDraw(ToxWindow* self) {
|
||||||
|
|
||||||
static void print_usage(ToxWindow* self) {
|
static void print_usage(ToxWindow* self) {
|
||||||
wattron(self->window, COLOR_PAIR(2) | A_BOLD);
|
wattron(self->window, COLOR_PAIR(2) | A_BOLD);
|
||||||
wprintw(self->window, "Usage:\n");
|
wprintw(self->window, "Commands:\n");
|
||||||
wattroff(self->window, A_BOLD);
|
wattroff(self->window, A_BOLD);
|
||||||
|
|
||||||
wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n");
|
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, " accept <number> : Accept friend request\n");
|
||||||
wprintw(self->window, " myid : Print your ID\n");
|
wprintw(self->window, " myid : Print your ID\n");
|
||||||
wprintw(self->window, " quit/exit : Exit program\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));
|
wattroff(self->window, COLOR_PAIR(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,6 +311,8 @@ static void prompt_onInit(ToxWindow* self) {
|
||||||
ToxWindow new_prompt() {
|
ToxWindow new_prompt() {
|
||||||
ToxWindow ret;
|
ToxWindow ret;
|
||||||
|
|
||||||
|
memset(&ret, 0, sizeof(ret));
|
||||||
|
|
||||||
ret.onKey = &prompt_onKey;
|
ret.onKey = &prompt_onKey;
|
||||||
ret.onDraw = &prompt_onDraw;
|
ret.onDraw = &prompt_onDraw;
|
||||||
ret.onInit = &prompt_onInit;
|
ret.onInit = &prompt_onInit;
|
||||||
|
|
|
@ -1,10 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Toxic -- Tox Curses Client
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct ToxWindow_ ToxWindow;
|
typedef struct ToxWindow_ ToxWindow;
|
||||||
|
|
||||||
struct ToxWindow_ {
|
struct ToxWindow_ {
|
||||||
void(*onKey)(ToxWindow*, int);
|
void(*onKey)(ToxWindow*, int);
|
||||||
void(*onDraw)(ToxWindow*);
|
void(*onDraw)(ToxWindow*);
|
||||||
void(*onInit)(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];
|
char title[256];
|
||||||
|
|
||||||
|
void* x;
|
||||||
|
bool blink;
|
||||||
|
|
||||||
WINDOW* window;
|
WINDOW* window;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user